DaewoongP / cerule-stream

Application Object detection using Neural Networks, Python and Open CV (with Raspberry pi)
1 stars 0 forks source link

[스트리밍]opencv->dash #14

Closed safecorners closed 6 years ago

safecorners commented 6 years ago
DaewoongP commented 6 years ago
  1. opencv -> rtsp 로 전송
  2. rtsp -> nginx
  3. nginx -> mpeg-dash
safecorners commented 6 years ago

https://sonnati.wordpress.com/2012/07/02/ffmpeg-the-swiss-army-knife-of-internet-streaming-part-v/ https://sonnati.wordpress.com/2011/08/08/ffmpeg-%e2%80%93-the-swiss-army-knife-of-internet-streaming-%e2%80%93-part-ii/ https://sonnati.wordpress.com/2011/08/19/ffmpeg-%e2%80%93-the-swiss-army-knife-of-internet-streaming-%e2%80%93-part-iii/

https://sonnati.wordpress.com/2011/08/30/ffmpeg-%e2%80%93-the-swiss-army-knife-of-internet-streaming-%e2%80%93-part-iv/

safecorners commented 6 years ago

Getting-started-with-nginx-rtmp Live streaming dash Bitmovin Web Player

safecorners commented 6 years ago

openCV VideoWriter

http://www.fourcc.org/codecs.php

safecorners commented 6 years ago

Out (openCV -> Nginx): 파이프라인으로 전송

command = 'ffmpeg -i - -f flv [streaming_url]'

import subprocess as sp

proc = sp.Popen(command, stdin=sp.PIPE,shell=False)
proc.stdin.write(frame.tostring())

참조: Read and Write Video Frames in Python Using FFMPEG OpenCV and RTMP stream Face Detection with Intel® Distribution for Python*

safecorners commented 6 years ago

mp4 파일 전송

$ ffmpeg -i toystory.mp4 -vcodec libx264 -f flv rtmp://localhost:1935/dash/live
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'toystory.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    creation_time   : 1970-01-01T00:00:00.000000Z
    encoder         : Lavf52.94.0
  Duration: 00:02:29.95, start: 0.000000, bitrate: 1787 kb/s
    Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 640x360 [SAR 1:1 DAR 16:9], 1629 kb/s, 29.97 fps, 29.97 tbr, 30k tbn, 59.94 tbc (default)
    Metadata:
      creation_time   : 1970-01-01T00:00:00.000000Z
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 151 kb/s (default)
    Metadata:
      creation_time   : 1970-01-01T00:00:00.000000Z
      handler_name    : SoundHandler
Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
  Stream #0:1 -> #0:1 (aac (native) -> mp3 (libmp3lame))
Press [q] to stop, [?] for help
[libx264 @ 0x7f9c9881c600] using SAR=1/1
[libx264 @ 0x7f9c9881c600] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
[libx264 @ 0x7f9c9881c600] profile High, level 3.0
[libx264 @ 0x7f9c9881c600] 264 - core 152 r2854 e9a5903 - H.264/MPEG-4 AVC codec - Copyleft 2003-2017 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=6 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, flv, to 'rtmp://localhost:1935/dash/live':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.12.100
    Stream #0:0(und): Video: h264 (libx264) ([7][0][0][0] / 0x0007), yuv420p, 640x360 [SAR 1:1 DAR 16:9], q=-1--1, 29.97 fps, 1k tbn, 29.97 tbc (default)
    Metadata:
      creation_time   : 1970-01-01T00:00:00.000000Z
      handler_name    : VideoHandler
      encoder         : Lavc58.18.100 libx264
    Side data:
      cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: -1
    Stream #0:1(und): Audio: mp3 (libmp3lame) ([2][0][0][0] / 0x0002), 44100 Hz, stereo, fltp (default)
    Metadata:
      creation_time   : 1970-01-01T00:00:00.000000Z
      handler_name    : SoundHandler
      encoder         : Lavc58.18.100 libmp3lame
[flv @ 0x7f9c98822400] Failed to update header with correct duration.664.1kbits/s speed= 3.5x
[flv @ 0x7f9c98822400] Failed to update header with correct filesize.
frame= 4494 fps=105 q=-1.0 Lsize=   12136kB time=00:02:29.86 bitrate= 663.4kbits/s speed= 3.5x
video:9616kB audio:2342kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 1.487614%
[libx264 @ 0x7f9c9881c600] frame I:106   Avg QP:18.67  size: 19113
[libx264 @ 0x7f9c9881c600] frame P:1760  Avg QP:22.44  size:  3264
[libx264 @ 0x7f9c9881c600] frame B:2628  Avg QP:25.66  size:   790
[libx264 @ 0x7f9c9881c600] consecutive B-frames: 16.8% 12.9%  8.3% 61.9%
[libx264 @ 0x7f9c9881c600] mb I  I16..4: 19.6% 46.9% 33.5%
[libx264 @ 0x7f9c9881c600] mb P  I16..4:  3.0%  7.1%  1.3%  P16..4: 28.4%  8.0%  5.0%  0.0%  0.0%    skip:47.4%
[libx264 @ 0x7f9c9881c600] mb B  I16..4:  0.4%  1.0%  0.2%  B16..8: 20.9%  2.1%  0.5%  direct: 1.2%  skip:73.8%  L0:43.6% L1:48.8% BI: 7.6%
[libx264 @ 0x7f9c9881c600] 8x8 transform intra:58.0% inter:69.1%
[libx264 @ 0x7f9c9881c600] coded y,uvDC,uvAC intra: 54.4% 72.4% 39.3% inter: 7.4% 11.6% 1.4%
[libx264 @ 0x7f9c9881c600] i16 v,h,dc,p: 40% 33% 12% 16%
[libx264 @ 0x7f9c9881c600] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 23% 22% 22%  4%  5%  6%  6%  5%  6%
[libx264 @ 0x7f9c9881c600] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 27% 24% 11%  5%  7%  7%  7%  5%  6%
[libx264 @ 0x7f9c9881c600] i8c dc,h,v,p: 48% 25% 21%  7%
[libx264 @ 0x7f9c9881c600] Weighted P-Frames: Y:8.0% UV:7.7%
[libx264 @ 0x7f9c9881c600] ref P L0: 75.9% 11.5%  8.8%  3.7%  0.1%
[libx264 @ 0x7f9c9881c600] ref B L0: 90.6%  7.8%  1.5%
[libx264 @ 0x7f9c9881c600] ref B L1: 97.5%  2.5%
[libx264 @ 0x7f9c9881c600] kb/s:525.31

전송이 끝났을시 아래와 같은 메시지가 나옴:

[flv @ 0x7f9c98822400] Failed to update header with correct duration.664.1kbits/s speed= 3.5x
[flv @ 0x7f9c98822400] Failed to update header with correct filesize.
safecorners commented 6 years ago

Subprocess 모듈 사용법

import subprocess

command = 'ffmpeg -i toystory.mp4 -vcodec libx264 -f flv rtmp://localhost:1935/dash/live'

proc = subprocess.Popen(
    command,
    stdout=subprocess.PIPE,
    shell=True
)
out, err = proc.communicate()
print(out)
safecorners commented 6 years ago

동영상 파일로 저장하는 방법과 rtmp서버로 푸시하는 법

import numpy as np
import subprocess as sp
import cv2

cap = cv2.VideoCapture("toystory.mp4")
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
fps = cap.get(cv2.CAP_PROP_FPS)
print(width, height, fps)

#url = 'rtmp://localhost:1935/dash/live'
#command = 'ffmpeg -i - -vcodec libx264 -f flv {}'.format(url)
#print(command)
#proc = sp.Popen(command, stdin=sp.PIPE, shell=True, bufsize=10**8)

command = ['ffmpeg',
        '-y', # (optional) overwrite output file if it exists
        '-f', 'rawvideo',
        '-vcodec','rawvideo',
        '-s', '640x360', # size of one frame
        '-pix_fmt', 'rgb24',
        '-r', '29.97',  # frames per second
        '-i', '-',  # The imput comes from a pipe
        '-an',  # Tells FFMPEG not to expect any audio
        '-vcodec', 'libx264',
        'my_output_videofile.mp4' ]

stream_command = ['ffmpeg',
        '-y', # (optional) overwrite output file if it exists
        '-f', 'rawvideo',
        '-vcodec','rawvideo',
        '-s', '640x360', # size of one frame
        '-pix_fmt', 'rgb24',
        '-r', '29.97',  # frames per second
        '-i', '-',  # The imput comes from a pipe
        '-an',  # Tells FFMPEG not to expect any audio
        '-vcodec', 'libx264',
        '-f', 'flv',
        'rtmp://localhost:1935/dash/live' ]

pipe = sp.Popen(command, stdin=sp.PIPE, stderr=sp.PIPE)
stream = sp.Popen(stream_command, stdin=sp.PIPE, stderr=sp.PIPE)
while cap.isOpened():
    # Capture frame-by-frame
    ret, frame = cap.read()  # frame size: 640x360x3(=691200)
    if ret:
        # Our operations on the frame come here
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        print(gray.size)
        # Display the resulting frame
        cv2.imshow('frame', gray)
        print(frame.size)  # 640x360x3(=691200)

        pipe.stdin.write(gray.tostring())
        stream.stdin.write(frame.tostring())
    else:
        break
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()