1

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:

enter image description here

-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:

enter image description here

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.

1 Answer 1

2

-c:av copy is not valid syntax and re-encodes the video. Only the first specifier a is honoured.

You can see this in the stream mapping

For -c:av copy:

Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> flv1 (flv))

For -vcodec copy -acodec copy:

Stream mapping:
  Stream #0:0 -> #0:0 (copy)

Before version 4.2, syntax matching for this wasn't strict so ffmpeg did not abort the command, or warn.


As to your main issue, the camera is producing a 2688x1520 resolution H.264 stream with an unknown (to me) keyframe interval. The former part means the decoder has to support at least AVC Level 5 - your target player may not. If the keyframe interval is large enough then the player will fail to decode the stream till it receives a KF.

To keep CPU low, your best bet is to tweak the camera output - a) a low keyframe interval (< 4 seconds), b) smaller frame size (smaller the better, but at most 1920x1080).

If those can't be done, you'll have to re-encode. Your -c:av copy command is using the old flv encoder, which is an older generation codec. I suggest using x264.

-vf scale=1920:1080:force_original_aspect_ratio=decrease -c:v libx264 -profile:v main -preset superfast

I inserted a scaler to keep the output frame size to under 1920x1080.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.