티스토리 뷰

3.13. 파이카메라 네트워크 스트림에 기록


이것은 비디오를 스트림에 녹화하는 것과 비슷하지만 BytesIO와 같은 메모리 내 스트림 대신 socket ()에서 생성 된 파일과 유사한 객체를 사용합니다. 네트워크 스트림에 캡처하는 예제와 달리 이미지 길이와 같은 것을 작성하여 네트워크 프로토콜을 복잡하게 만들 필요가 없습니다. 이번에는 비디오 프레임의 연속적인 스트림을 보내고 있습니다. (훨씬 효율적인 형식 임에도 불구하고 필연적으로 이러한 정보가 통합되어 있습니다.) 따라서 녹화를 네트워크 소켓으로 바로 내보낼 수 있습니다.


첫째, 서버 측 스크립트는 비디오 스트림을 읽고 미디어 플레이어에 파이프하여 표시합니다.


import socket
import subprocess

# Start a socket listening for connections on 0.0.0.0:8000 (0.0.0.0 means
# all interfaces)
server_socket = socket.socket()
server_socket.bind(('0.0.0.0', 8000))
server_socket.listen(0)

# Accept a single connection and make a file-like object out of it
connection = server_socket.accept()[0].makefile('rb')
try:
    # Run a viewer with an appropriate command line. Uncomment the mplayer
    # version if you would prefer to use mplayer instead of VLC
    cmdline = ['vlc', '--demux', 'h264', '-']
    #cmdline = ['mplayer', '-fps', '25', '-cache', '1024', '-']
    player = subprocess.Popen(cmdline, stdin=subprocess.PIPE)
    while True:
        # Repeatedly read 1k of data from the connection and write it to
        # the media player's stdin
        data = connection.read(1024)
        if not data:
            break
        player.stdin.write(data)
finally:
    connection.close()
    server_socket.close()
    player.terminate()


참고: Windows에서이 스크립트를 실행하는 경우 VLC 또는 mplayer 실행 파일에 대한 전체 경로를 제공해야 할 수 있습니다. 이 스크립트를 Mac OS X에서 실행하고 MacPorts에서 설치된 Python을 사용하는 경우 MacPorts의 VLC 또는 mplayer도 설치했는지 확인하십시오.



이 설정을 사용하면 몇 초의 지연이 발생할 수 있습니다. 이것은 정상적인 현상이며 미디어 플레이어가 신뢰할 수없는 네트워크 스트림으로부터 보호하기 위해 몇 초간 버퍼를 유지하기 때문입니다. 일부 미디어 플레이어 (이 경우에는 특히 mplayer)를 사용하면 사용자가 버퍼의 끝으로 건너 뛰고 (mplayer에서 오른쪽 커서 키 누르기) 지연되거나 끊어진 네트워크 패킷이 재생을 방해 할 수있는 위험을 증가시켜 지연 시간을 줄일 수 있습니다.


이제 네트워크 소켓에서 생성 된 파일과 유사한 객체에 대한 기록을 시작하는 클라이언트 측 스크립트의 경우 :


import socket
import time
import picamera

# Connect a client socket to my_server:8000 (change my_server to the
# hostname of your server)
client_socket = socket.socket()
client_socket.connect(('my_server', 8000))

# Make a file-like object out of the connection
connection = client_socket.makefile('wb')
try:
    camera = picamera.PiCamera()
    camera.resolution = (640, 480)
    camera.framerate = 24
    # Start a preview and let the camera warm up for 2 seconds
    camera.start_preview()
    time.sleep(2)
    # Start recording, sending the output to the connection for 60
    # seconds, then stop
    camera.start_recording(connection, format='h264')
    camera.wait_recording(60)
    camera.stop_recording()
finally:
    connection.close()
    client_socket.close()


위의 효과는 netcat과 raspivid 실행 파일의 조합으로 훨씬 쉽게 (적어도 Linux에서는) 달성된다는 점에 유의해야합니다. 예 :

# on the server
$ nc -l 8000 | vlc --demux h264 -

# on the client
raspivid -w 640 -h 480 -t 60000 -o - | nc my_server 8000

그러나이 방법은 비디오 스트리밍 응용 프로그램의 시작점으로 사용됩니다. 이 조리법의 방향을 비교적 쉽게 뒤집을 수도 있습니다. 이 시나리오에서 Pi는 클라이언트와의 연결을 기다리는 서버 역할을합니다. 연결을 수락하면 60 초 동안 비디오 스트리밍을 시작합니다. 데모 용으로 또 다른 변형은 연결시 스트리밍이 더 빨리 시작될 수 있도록 연결을 기다리는 대신 카메라를 곧바로 초기화한다는 것입니다.



import socket
import time
import picamera

camera = picamera.PiCamera()
camera.resolution = (640, 480)
camera.framerate = 24

server_socket = socket.socket()
server_socket.bind(('0.0.0.0', 8000))
server_socket.listen(0)

# Accept a single connection and make a file-like object out of it
connection = server_socket.accept()[0].makefile('wb')
try:
    camera.start_recording(connection, format='h264')
    camera.wait_recording(60)
    camera.stop_recording()
finally:
    connection.close()
    server_socket.close()


이 설정의 한 가지 장점은 클라이언트 측에서 스크립트가 필요 없다는 것입니다. VLC를 네트워크 URL과 함께 간단하게 사용할 수 있습니다.

vlc tcp/h264://my_pi_address:8000/

참고 : VLC (또는 mplayer)는 Pi에서 재생되지 않습니다. 또한 (현재) 디코딩을 위해 GPU를 사용할 수 없으므로 Pi의 CPU에서 비디오 디코딩을 시도합니다 (이는 작업에 충분히 강력하지 않습니다). 이러한 응용 프로그램을보다 빠른 시스템에서 실행해야합니다 ( "빠른"이란 용어는 여기에서 상대적 용어입니다. 심지어 Atom 전원식 넷북도 비 -HD 해상도의 작업에 충분히 빠르지 만).

댓글
최근에 달린 댓글
글 보관함
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
Total
Today
Yesterday
    뽀로로친구에디
    최근에 올라온 글