0

I'm trying to write video frames to an RTMP stream using FFMPEG and Python subsystem. The code will try to get videos in a 'ReceivedRecording' then it is stream to a RTMP streaming server using nginx. My method seems to work, but at times, the code will stop running due to

[flv @ 0x55b933694b40] Failed to update header with correct duration.
[flv @ 0x55b933694b40] Failed to update header with correct filesize.

and

Conversion failed

then

BrokenPipeError: [Errno 32] Broken pipe

Here my implementation of the task:

import subprocess
import cv2
rtmp_url = "rtmp://..."

path = 'ReceivedRecording'

received_video_path = 'ReceivedRecording'
while True:
    video_files = [filenames for filenames in sorted(
        os.listdir(received_video_path))]
    # Loop through the videos and concatenate them
    for filename in video_files[:len(video_files)-1]:
        video = cv2.VideoCapture(os.path.join(received_video_path, filename))

        if p is None:
            fps = int(video.get(cv2.CAP_PROP_FPS))
            width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH))
            height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))
            # command and params for ffmpeg
            command = ['ffmpeg',
                        '-y',
                        '-f', 'rawvideo',
                        '-vcodec', 'rawvideo',
                        '-pix_fmt', 'bgr24',
                        '-s', "{}x{}".format(width, height),
                        '-re',
                        '-r', '5',
                        '-i', '-',
                        # '-filter:v', 'setpts=4.0*PTS',
                        '-c:v', 'libx264',
                        '-pix_fmt', 'yuv420p',
                        '-preset', 'ultrafast',
                        '-tune','zerolatency',
                        '-vsync','vfr',
                        # '-crf','23',
                        '-f', 'flv',
                        rtmp_url]
            
            # using subprocess and pipe to fetch frame data
            p = subprocess.Popen(command, stdin=subprocess.PIPE)
        else:

            # Loop through the frames of each video
            while True:
                start_time = time.time()

                ret, frame = video.read()
                if not ret:
                    # End of video, move to next video
                    video.release()
                    break

                p.stdin.write(frame.tobytes())

            os.remove(os.path.join(received_video_path, filename))

Here is my nginx rtmp settings:

rtmp {
    server {
        listen 1935;
        chunk_size 7096;

        application live {
            live on;
            record off;
            push rtmp://...;
        }
    }
}

Here is the log file:

av_interleaved_write_frame(): Connection reset by peer
No more output streams to write to, finishing.
[flv @ 0x5561d1ca9b40] Failed to update header with correct duration.
[flv @ 0x5561d1ca9b40] Failed to update header with correct filesize.
Error writing trailer of rtmp://...: Connection reset by peer
frame=    1 fps=0.0 q=20.0 Lsize=    1024kB time=00:00:00.00 bitrate=8390776.0kbits/s speed=0.00619x
video:1053kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
Input file #0 (pipe:):
  Input stream #0:0 (video): 1 packets read (11059200 bytes); 1 frames decoded;
  Total: 1 packets (11059200 bytes) demuxed
Output file #0 (rtmp://...):
  Output stream #0:0 (video): 1 frames encoded; 1 packets muxed (1077799 bytes);
  Total: 1 packets (1077799 bytes) muxed
1 frames successfully decoded, 0 decoding errors
[AVIOContext @ 0x5561d1cad380] Statistics: 0 seeks, 35 writeouts
[rtmp @ 0x5561d1cb7b80] Deleting stream...
[libx264 @ 0x5561d1caae40] frame I:1     Avg QP:20.00  size:1077192
[libx264 @ 0x5561d1caae40] mb I  I16..4: 100.0%  0.0%  0.0%
[libx264 @ 0x5561d1caae40] coded y,uvDC,uvAC intra: 92.2% 50.5% 10.2%
[libx264 @ 0x5561d1caae40] i16 v,h,dc,p: 34% 16% 37% 12%
[libx264 @ 0x5561d1caae40] i8c dc,h,v,p: 35% 23% 33%  9%
[libx264 @ 0x5561d1caae40] kb/s:43087.68
[AVIOContext @ 0x5561d1ca6a80] Statistics: 11059200 bytes read, 0 seeks
Conversion failed!
  • I suggest you to try creating synthetic video frames as in my [following answer](https://stackoverflow.com/a/61281547/4926757). Looping through the videos may fail in case the resolution is not identical in all the video files. I also suggest you to stream the video to `localhost` (to `127.0.0.1`) for making sure there are no communication related issues. According to [this answer](https://stackoverflow.com/a/63816448/4926757), you may add `-flvflags no_duration_filesize` (I think it's just a warning). – Rotem May 08 '23 at 16:40
  • The videos are all in the exact resolution. It seems to work fine when I try to stream a single video. But I'm trying to stream the results of my computer visions, where each frame is detected, combined into small chunks, and then stream. Is there anything else I can try? – Loc Bui Nhien May 09 '23 at 03:44
  • Are you saying that the issue is related to the fact that you are reading multiple videos? Have you tried my suggestions??? For making the issue reproducible, I suggest you to check with synthetic videos. Make a clean videos folder, and use FFmpeg for creating synthetic videos: `ffmpeg -f lavfi -i testsrc=size=1920x1080:rate=30:duration=1000 -vcodec libx264 -g 10 -f segment -segment_time 10 -reset_timestamps 1 %04d.mp4`. In case it fails, you may post a reproducible question. Edit the question and replace `rtmp_url = "rtmp://..."` with reproducible example (use localhost). – Rotem May 09 '23 at 08:11
  • I tried your suggestions before making the last comment, including streaming to `localhost` following your other answer, and still have the same problem. But I fixed it now thankfully. It has to do with some parameters of FFmpeg. Thank you for your insights and know-how on the matter. It helps me a lot to get everything fixed. – Loc Bui Nhien May 10 '23 at 08:37

0 Answers0