I'm not an expert at ffmpeg, or video tech by any means. I have very little experience with it.
I have an IP camera that produces an h264 stream. I'm trying to use ffmpeg, and nginx (with the rtmp module) to restream the live camera feed to multiple clients. I am NOT trying to re-encode anything. The less CPU-intensive that my ffmpeg command is, the better.
If I use an older version of ffmpeg (version 4.1.4), it supports 2 ways of copying the video and audio feeds from the source stream without re-encoding them: -c:av copy
and -vcodec copy -acodec copy
. From what I understand, these are supposed to act exactly the same, but that doesn't appear to be the case.
-c:av copy
output:
# ffmpeg -err_detect ignore_err -rtsp_transport tcp -re -i rtsp://USERNAME:PASSWORD@IP/Streaming/Channels/701/httpPreview -c:av copy -f flv rtmp://127.0.0.1/stream/stream1
ffmpeg version 4.1.4-static https://johnvansickle.com/ffmpeg/ Copyright (c) 2000-2019 the FFmpeg developers
built with gcc 6.3.0 (Debian 6.3.0-18+deb9u1) 20170516
configuration: --enable-gpl --enable-version3 --enable-static --disable-debug --disable-ffplay --disable-indev=sndio --disable-outdev=sndio --cc=gcc-6 --enable-fontconfig --enable-frei0r --enable-gnutls --enable-gmp --enable-libgme --enable-gray --enable-libaom --enable-libfribidi --enable-libass --enable-libvmaf --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librubberband --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libvorbis --enable-libopus --enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzvbi --enable-libzimg
libavutil 56. 22.100 / 56. 22.100
libavcodec 58. 35.100 / 58. 35.100
libavformat 58. 20.100 / 58. 20.100
libavdevice 58. 5.100 / 58. 5.100
libavfilter 7. 40.101 / 7. 40.101
libswscale 5. 3.100 / 5. 3.100
libswresample 3. 3.100 / 3. 3.100
libpostproc 55. 3.100 / 55. 3.100
Input #0, rtsp, from 'rtsp://USERNAME:PASSWORD@IP/Streaming/Channels/701/httpPreview':
Metadata:
title : Media Server V3.4.92
comment : Media Server Session Description : standard
Duration: N/A, start: 0.500000, bitrate: N/A
Stream #0:0: Video: h264 (Main), yuvj420p(pc, bt709, progressive), 2688x1520 [SAR 1:1 DAR 168:95], 20 fps, 20 tbr, 90k tbn, 40 tbc
Stream mapping:
Stream #0:0 -> #0:0 (h264 (native) -> flv1 (flv))
Press [q] to stop, [?] for help
[swscaler @ 0x5f72cc0] deprecated pixel format used, make sure you did set range correctly
Output #0, flv, to 'rtmp://127.0.0.1/stream/stream1':
Metadata:
title : Media Server V3.4.92
comment : Media Server Session Description : standard
encoder : Lavf58.20.100
Stream #0:0: Video: flv1 (flv) ([2][0][0][0] / 0x0002), yuv420p, 2688x1520 [SAR 1:1 DAR 168:95], q=2-31, 200 kb/s, 20 fps, 1k tbn, 20 tbc
Metadata:
encoder : Lavc58.35.100 flv
Side data:
cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1
[flv @ 0x5f55780] Failed to update header with correct duration.ate=2762.3kbits/s dup=0 drop=5 speed=0.956x
[flv @ 0x5f55780] Failed to update header with correct filesize.
frame= 85 fps= 19 q=24.8 Lsize= 1495kB time=00:00:04.20 bitrate=2916.0kbits/s dup=0 drop=5 speed=0.943x
video:1494kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.108328%
resulting video:
-vcodec copy -acodec copy
output:
# ffmpeg -err_detect ignore_err -rtsp_transport tcp -re -i rtsp://USERNAME:PASSWORD@IP/Streaming/Channels/701/httpPreview -acodec copy -vcodec copy -f flv rtmp://127.0.0.1/stream/stream1
ffmpeg version 4.1.4-static https://johnvansickle.com/ffmpeg/ Copyright (c) 2000-2019 the FFmpeg developers
built with gcc 6.3.0 (Debian 6.3.0-18+deb9u1) 20170516
configuration: --enable-gpl --enable-version3 --enable-static --disable-debug --disable-ffplay --disable-indev=sndio --disable-outdev=sndio --cc=gcc-6 --enable-fontconfig --enable-frei0r --enable-gnutls --enable-gmp --enable-libgme --enable-gray --enable-libaom --enable-libfribidi --enable-libass --enable-libvmaf --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librubberband --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libvorbis --enable-libopus --enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzvbi --enable-libzimg
libavutil 56. 22.100 / 56. 22.100
libavcodec 58. 35.100 / 58. 35.100
libavformat 58. 20.100 / 58. 20.100
libavdevice 58. 5.100 / 58. 5.100
libavfilter 7. 40.101 / 7. 40.101
libswscale 5. 3.100 / 5. 3.100
libswresample 3. 3.100 / 3. 3.100
libpostproc 55. 3.100 / 55. 3.100
Input #0, rtsp, from 'rtsp://USERNAME:PASSWORD@IP/Streaming/Channels/701/httpPreview':
Metadata:
title : Media Server V3.4.92
comment : Media Server Session Description : standard
Duration: N/A, start: 0.350000, bitrate: N/A
Stream #0:0: Video: h264 (Main), yuvj420p(pc, bt709, progressive), 2688x1520 [SAR 1:1 DAR 168:95], 20 fps, 20 tbr, 90k tbn, 40 tbc
Output #0, flv, to 'rtmp://127.0.0.1/stream/stream1':
Metadata:
title : Media Server V3.4.92
comment : Media Server Session Description : standard
encoder : Lavf58.20.100
Stream #0:0: Video: h264 (Main) ([7][0][0][0] / 0x0007), yuvj420p(pc, bt709, progressive), 2688x1520 [SAR 1:1 DAR 168:95], q=2-31, 20 fps, 20 tbr, 1k tbn, 90k tbc
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Press [q] to stop, [?] for help
[flv @ 0x6670a40] Failed to update header with correct duration.ate=3111.6kbits/s speed=1.03x
[flv @ 0x6670a40] Failed to update header with correct filesize.
frame= 38 fps= 25 q=-1.0 Lsize= 589kB time=00:00:01.55 bitrate=3111.7kbits/s speed=1.01x
video:588kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.192649%
resulting video:
As you can clearly see, the output of -vcodec copy -acodec copy
is clearly far less pixelated. While that sounds like a good thing, it seems like FFMPEG does more work to process the image, which may explain why when nginx re-streams the feed, and I try to connect to it with VLC, the -c:av copy
feed (worse quality) works almost every time, whereas the -vcodec copy -acodec copy
feed sometimes has VLC throw an error that it can't connect, and other times connects, but just shows a video that's all black.
The problem with sticking with -c:av copy
is that when I use a more-recent version of ffmpeg (like the 4.2.1 static build from here: https://johnvansickle.com/ffmpeg/), they don't even have the -c:av copy
arg anymore, so my only option is to use -vcodec copy -acodec copy
, and I experience the same problems with VLC. This means right now, I can only use the old FFMPEG version.
Am I doing something wrong? I want ffmpeg to do as little processing as possible - I just want it to copy the video stream to an flv container as-is, and publish it to nginx. I don't care if this results in a bit of pixelation - the quality isn't a massive deal for me.