FFmpeg changes framerate to Variable when remuxing - ffmpeg

I'm trying to change .MKV container to .MP4 using FFmpeg without re-encoding video stream:
ffmpeg -i input.mkv -c copy output.mp4
The input file has Constant framerate:
Frame rate mode: Constant
Frame rate : 30.000 fps
However, the output file got a variable framerate according to Mediainfo:
Frame rate mode : Variable
Frame rate : 30.000 fps
Minimum frame rate : 29.412 fps
Maximum frame rate : 30.303 fps
Total number of frames stays the same.
The output from ffmpeg:
Output #0, mp4, to 'input.mp4':
Metadata:
encoder : Lavf56.40.101
Stream #0:0: Video: h264 ([33][0][0][0] / 0x0021), yuv420p, 2560x1440 [SAR 1:1 DAR 16:9], q=2-31, 30 fps, 30 tbr, 16k tbn, 1k tbc (default)
Metadata:
DURATION : 00:05:00.766000000
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Press [q] to stop, [?] for help
frame= 9023 fps=0.0 q=-1.0 Lsize= 209201kB time=00:05:00.66 bitrate=5699.9kbits/s
video:209045kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.074948%
Is it possible to set constant bitrate for the output? I've tried -vsync and -r but they seem to be ignored when -c copy is set.

Related

Can I test funcion of nvidia decoder (nvdec/cuvid) on generated ffmpeg video?

goal: In my script I try to check if nvdec on my graphics card is available/functional.
I don't have any source video (H.264 / H.265) to use as input at this time intentionally, so I want to generate it.
It is also not necessary to use an encoder, because I do not need the output file.
I'm testing the exit code of command ffmpeg ($?).
I use nvidia-smi for check dec/enc load.
My attempt:
ffmpeg -y -hwaccel cuda -hwaccel_output_format cuda -c:v h264_cuvid -f lavfi -i testsrc="duration=5:size=1920x1080:rate=25" -c:v copy test.ts
output of my commands:
Input #0, lavfi, from 'testsrc=duration=5:size=1920x1080:rate=25':
Duration: N/A, bitrate: N/A
Stream #0:0: Video: h264, rgb24, 1920x1080 [SAR 1:1 DAR 16:9], 25 tbn
Stream mapping:
Stream #0:0 -> #0:0 (h264 (h264_cuvid) -> wrapped_avframe (native))
Press [q] to stop, [?] for help
No information about the input framerate is available. Falling back to a default value of 25fps for output stream #0:0. Use the -r option if you want a different framerate.
Output #0, null, to 'pipe:':
Metadata:
encoder : Lavf58.65.101
Stream #0:0: Video: wrapped_avframe, rgb24, 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 200 kb/s, 25 fps, 25 tbn
Metadata:
encoder : Lavc58.119.100 wrapped_avframe
frame= 0 fps=0.0 q=0.0 Lsize=N/A time=00:00:00.00 bitrate=N/A speed= 0x
video:0kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
Output file is empty, nothing was encoded (check -ss / -t / -frames parameters if used)
I triead add -t 5 before test.ts but nothing changed.
Output ts file has zero size.
If I debug the command, I expect to add it to the end "-f null - 2>/dev/null". Output file is only for debug purposes.
Thank you.
You need to first generate the video with a H.264 encoder and then try decoding it separately afterwards.
ffmpeg -y -f lavfi -i "testsrc2=duration=5:size=1920x1080:rate=25" -c:v h264 test.ts
ffmpeg -c:v h264_cuvid -i test.ts -f null -

webm to mp4 conversion using ffmpeg ubuntu

I have video and I want to convert that to mp4
It is working fine for the .flv and other formats. But when I'm trying to convert webm to mp4 the video is not getting converted
ffmpeg -i /input.webm /output.mp4
It is only converting to a 48kb file. The actual size of video is 850mb
I am getting this
Output #0, mp4, to '/output.mp4':
Metadata:
encoder : Lavf56.40.101
Stream #0:0(eng): Video: h264 (libx264) ([33][0][0][0] / 0x0021), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], q=-1--1, 29.97 fps, 30k tbn, 29.97 tbc (default)
Metadata:
encoder : Lavc56.60.100 libx264
Stream mapping:
Stream #0:0 -> #0:0 (vp9 (native) -> h264 (libx264))
Press [q] to stop, [?] for help
Killed 21 fps=0.0 q=0.0 size= 0kB time=00:00:00.00 bitrate=N/A
It is working locally but on live server it's not generating the output as expected

ffmpeg - duration usage in input text file

I am trying to use ffmpeg to concatenate video segments with some black screen. To do that I've first generated a blank 10-second video (no audio track) with:
$ ffmpeg -f lavfi -i color=black:s=320x240:r=1 -f lavfi -i anullsrc -t 10 -vcodec libvpx -an blank.mkv
I then created the simplest possible scenario within input.txt file (contents below) in order to have three seconds of black screen followed by some video (no audio track):
file 'blank.mkv'
duration 3
file 'video_example.mkv'
And, finally, ran the following ffmpeg command to concat the contents of that input file:
$ ffmpeg -f concat -i input.txt -codec:v copy -codec:a copy output.mkv
The issue that I have is that the duration 3 is not considered, so the final video still has ten seconds of black frames (instead of three) followed by my video. And also "Non-monotonous DTS in output stream 0:0 ..." message is shown when using duration x in the file. If I remove duration the warnings are gone and getting the 10-second black screen first output as well.
Full output of the ffmpeg concat command:
$ ffmpeg -hide_banner -f concat -i input.txt -codec:v copy -codec:a copy output.mkv
Input #0, concat, from 'input.txt':
Duration: N/A, start: 0.000000, bitrate: N/A
Stream #0:0: Video: vp8, yuv420p(progressive), 320x240, SAR 1:1 DAR 4:3, 1 fps, 1 tbr, 1k tbn, 1k tbc
Metadata:
ENCODER : Lavc57.107.100 libvpx
DURATION : 00:00:10.000000000
File 'output.mkv' already exists. Overwrite ? [y/N] y
Output #0, matroska, to 'output.mkv':
Metadata:
encoder : Lavf57.83.100
Stream #0:0: Video: vp8 (VP80 / 0x30385056), yuv420p(progressive), 320x240 [SAR 1:1 DAR 4:3], q=2-31, 1 fps, 1 tbr, 1k tbn, 1k tbc
Metadata:
ENCODER : Lavc57.107.100 libvpx
DURATION : 00:00:10.000000000
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Press [q] to stop, [?] for help
[concat # 000000000031a440] DTS 3000 < 9000 out of order
[matroska # 0000000000328420] Non-monotonous DTS in output stream 0:0; previous: 9000, current: 3000; changing to 9000. This may result in incorrect timestamps in the output file.
[matroska # 0000000000328420] Non-monotonous DTS in output stream 0:0; previous: 9000, current: 4001; changing to 9000. This may result in incorrect timestamps in the output file.
[matroska # 0000000000328420] Non-monotonous DTS in output stream 0:0; previous: 9000, current: 4998; changing to 9000. This may result in incorrect timestamps in the output file.
[matroska # 0000000000328420] Non-monotonous DTS in output stream 0:0; previous: 9000, current: 6004; changing to 9000. This may result in incorrect timestamps in the output file.
[matroska # 0000000000328420] Non-monotonous DTS in output stream 0:0; previous: 9000, current: 7002; changing to 9000. This may result in incorrect timestamps in the output file.
[matroska # 0000000000328420] Non-monotonous DTS in output stream 0:0; previous: 9000, current: 8005; changing to 9000. This may result in incorrect timestamps in the output file.
frame= 5794 fps=0.0 q=-1.0 Lsize= 7109kB time=01:37:09.70 bitrate= 10.0kbits/s speed=5.16e+004x
video:7043kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.926229%
Any idea what am I doing wrong? The warning seems to hint towards the issue here.
Other possibly useful info:
$ ffprobe -hide_banner blank.mkv
Input #0, matroska,webm, from 'blank.mkv':
Metadata:
ENCODER : Lavf57.83.100
Duration: 00:00:10.00, start: 0.000000, bitrate: 1 kb/s
Stream #0:0: Video: vp8, yuv420p(progressive), 320x240, SAR 1:1 DAR 4:3, 1 fps, 1 tbr, 1k tbn, 1k tbc (default)
Metadata:
ENCODER : Lavc57.107.100 libvpx
DURATION : 00:00:10.000000000
$ ffprobe -hide_banner video_example.mkv
Input #0, matroska,webm, from 'video_example.mkv':
Metadata:
encoder : GStreamer matroskamux version 1.8.1.1
creation_time : 2018-05-04T17:57:04.000000Z
Duration: 01:37:08.70, start: 15434.269000, bitrate: 9 kb/s
Stream #0:0(eng): Video: vp8, yuv420p(progressive), 320x240, SAR 1:1 DAR 4:3, 1 fps, 1 tbr, 1k tbn, 1k tbc (default)
Metadata:
title : Video
$ ffmpeg -v
ffmpeg version 3.4.2 Copyright (c) 2000-2018 the FFmpeg developers
built with gcc 7.3.0 (GCC)
For video and audio files, inpoint/outpoint have to be used.
file 'blank.mkv'
outpoint 3
file 'video_example.mkv'
duration is useful for single images, like when making a slideshow, or raw audio/video streams where ffmpeg can't reliably discover the media duration.

How to generate an RTMP test stream using ffmpeg command?

I would like to test my streaming infrastructure by generating an RTMP test video with a timestamp. This could look like that screen. The image doesn't matter. I'm after the working stream generated on-the-fly and timestamp only. I intend to use the ffmpeg tool for that purpose. The command could look something like
$ ffmpeg -i image.png \
-vf drawtext="fontfile=/Library/Fonts/Arial.ttf: \
timecode='00\:00\:00\:00': r=1: fontcolor=white: \
fontsize=24: box=1: boxcolor=black#0.5: \
boxborderw=5: x=(w-text_w)/2: y=(h-text_h)/2" \
-f flv rtmp://localhost/live/test
I do run locally a streaming server based on NGINX and its RTMP module.
However, the above command gives me the following error:
Input #0, png_pipe, from 'image.png':
Duration: N/A, bitrate: N/A
Stream #0:0: Video: png, rgb24(pc), 768x576 [SAR 7874:7874 DAR 4:3], 25 tbr, 25 tbn, 25 tbc
Stream mapping:
Stream #0:0 -> #0:0 (png (native) -> flv1 (flv))
Press [q] to stop, [?] for help
[Parsed_drawtext_0 # 0x7fb78450ece0] Using non-standard frame rate 1/1
Output #0, flv, to 'rtmp://localhost/live/test':
Metadata:
encoder : Lavf57.71.100
Stream #0:0: Video: flv1 (flv) ([2][0][0][0] / 0x0002), yuv420p, 768x576 [SAR 1:1 DAR 4:3], q=2-31, 200 kb/s, 25 fps, 1k tbn, 25 tbc
Metadata:
encoder : Lavc57.89.100 flv
Side data:
cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1
[flv # 0x7fb785812a00] Failed to update header with correct duration.
[flv # 0x7fb785812a00] Failed to update header with correct filesize.
frame= 1 fps=0.0 q=8.6 Lsize= 50kB time=00:00:00.00 bitrate=406016.0kbits/s speed=0.019x
video:49kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.451271%
The streaming server operates as expected. The problem is with the command. Would anyone be able to help me?
ffmpeg has testsrc you can use as a test source input stream:
ffmpeg -r 30 -f lavfi -i testsrc -vf scale=1280:960 -vcodec libx264 -profile:v baseline -pix_fmt yuv420p -f flv rtmp://localhost/live/test
-r, scaling, profile, etc are just an example and can be ommited/played with. The point is using -i testsrc

What does the fps mean in the ffmpeg output?

I am streaming a static png file with ffmpeg and it uses basically all my CPU. It seems a bit greedy to me, and even though I limited the fps on the input and output size, I am seeing a huge fps printed out.
w:\ffmpeg\bin>ffmpeg.exe -loop 1 -framerate 1 -i w:\colorbar2.png -r 10 -vcodec libx264 -pix_fmt yuv420p -r 10 -f mpegts udp://127.0.0.1:10001?pkt_size=1316
ffmpeg version N-68778-g5c7227b Copyright (c) 2000-2014 the FFmpeg developers
built on Dec 29 2014 22:12:54 with gcc 4.9.2 (GCC)
Input #0, png_pipe, from 'w:\colorbar2.png':
Duration: N/A, bitrate: N/A
Stream #0:0: Video: png, pal8, 320x240 [SAR 3779:3779 DAR 4:3], 1 fps, 1 tbr, 1 tbn, 1 tbc
[libx264 # 00000000002fb320] using SAR=1/1
[libx264 # 00000000002fb320] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX
[libx264 # 00000000002fb320] profile High, level 1.2
Output #0, mpegts, to 'udp://127.0.0.1:10001?pkt_size=1316':
Metadata:
encoder : Lavf56.16.102
Stream #0:0: Video: h264 (libx264), yuv420p, 320x240 [SAR 1:1 DAR 4:3], q=-1--1, 10 fps, 90k tbn, 10 tbc
Metadata:
encoder : Lavc56.19.100 libx264
Stream mapping:
Stream #0:0 -> #0:0 (png (native) -> h264 (libx264))
Press [q] to stop, [?] for help
frame=561310 fps=579 q=25.0 size= 144960kB time=15:35:25.80 bitrate= 21.2kbits/s dup=505179 drop=0
As you can see the frame counter goes up quickly and fps=579 is reported on the last line. I am confused now, what does that fps mean, if above the low frame per secs are also mentioned (output 10fps, input 1 fps)
What am I doing wrong and how could I reduce CPU load more given that it's a static file that is being streamed.
Thanks!
ffmpeg attempts to decode and encode as fast as it can. Just because you set the output to be 10 frames per second does not mean that it will (de|en)code realtime at 10 frames per second.
Try the -re input option. From the ffmpeg cli-tool documentation:
Read input at native frame rate. Mainly used to simulate a grab device
or live input stream (e.g. when reading from a file). Should not be
used with actual grab devices or live input streams (where it can
cause packet loss). By default ffmpeg attempts to read the input(s)
as fast as possible. This option will slow down the reading of the
input(s) to the native frame rate of the input(s). It is useful for
real-time output (e.g. live streaming).
Example:
ffmpeg.exe -re -loop 1 -framerate 10 -i w:\colorbar2.png -c:v libx264 \
-tune stillimage -pix_fmt yuv420p -f mpegts udp://127.0.0.1:10001?pkt_size=1316

Resources