ffmpeg 2 pass encoding- understand the statistics in the output .log file - ffmpeg

I am using 2 pass encoder to encode my input video with a target bitrate.
I want to get the encoder (x264) statistics from the first pass- these statistics are written to ffmpeg2pass.log
the output for each frame looks like that:
in:2 out:2 type:B dur:2 cpbdur:2 q:28.41 aq:25.07 tex:4721 mv:2357 misc:2266 imb:24 pmb:527 smb:3049 d:- ref:0 ;
How can I found is the meaning of each value? (for example, mv is motion vectors, but what is the meaning of misc, imb, pmb etc.?)
ffmpeg command used:
ffmpeg -f rawvideo -pix_fmt yuv422p16le -s:v 1280x720 -i "input_file.yuv" -c:v libx264 -pass 1 -stats -vstats -passlogfile "log_file_prefix" -f mp4 -y "output.mp4" &&
ffmpeg -f rawvideo -pix_fmt yuv422p16le -s:v 1280x720 -i "input_file.yuv" -c:v libx264 -pass 2 -passlogfile "log_file_prefix" -y "output.mp4"

In: display/input frame number
Out: coded frame number
Type: frame type
q: frame quantization value
Tex: the bit size used for residual
Mv: bit size for mvs
Misc: for other bit sizes
Imb: number of internal macroblocks
Pmb: number of inter macroblocks
Smb: skip the number of skip macroblocks
d: the best mode for this frame
Ref: the number of times each ref is used in the list
w: the optimal weight of this frame (if the weight is turned on)

Related

FFMPEG vsync drop and regeneration

According to the ffmpeg documentation
-vsync parameter
Video sync method. For compatibility reasons old values can be specified as numbers. Newly added values will have to be
specified as strings always.
drop
As passthrough but destroys all timestamps, making the muxer
generate fresh timestamps based on frame-rate.
It appears that the mpegts mux does not regenerate the timestamps correctly (PTS/DTS); however, piping the output after vsync drop to a second process as raw h264 does force mpegts to regenerate the PTS.
Generate test stream
ffmpeg -f lavfi -i testsrc=duration=20:size=1280x720:rate=50 -pix_fmt yuv420p -c:v libx264 -b:v 4000000 -x264-params ref=1:bframes=0:vbv-maxrate=4500:vbv-bufsize=4000:nal-hrd=cbr:aud=1:bframes=0:intra-refresh=1:keyint=30:min-keyint=30:scenecut=0 -f mpegts -muxrate 5985920 -pcr_period 20 video.ts -y
Generate output ts that has correctly spaced PTS values
ffmpeg -i video.ts -vsync drop -c:v copy -bsf:v h264_mp4toannexb -f h264 - | ffmpeg -fflags +igndts -fflags +nofillin -fflags +genpts -r 50 -i - -c:v copy -f mpegts -muxrate 5985920 video_all_pts_ok.ts -y
Generate output ts where all PTS are zero
ffmpeg -i video.ts -vsync drop -c:v copy -bsf:v h264_mp4toannexb -f mpegts - | ffmpeg -fflags +igndts -fflags +nofillin -fflags +genpts -r 50 -i - -c:v copy -f mpegts -muxrate 5985920 video_all_pts_zero.ts -y
It appears that vsync drop does destroy them but the mpegts doesn't regenerate them? Any ideas on what needs adding to get it to work as a single ffmpeg command?
Tested on both Linux and Windows with the same result
Try recoding the video just using -vsync 1, without -fflags +genpts. I found some good information here. This guy talking about streaming video. So highest quality isn't his objective. But there is useful info.
https://videoblerg.wordpress.com/2017/11/10/ffmpeg-and-how-to-use-it-wrong/
Section one – Constant frame rate
"-r is used to specify the output frame rate. This must be the same as the input frame rate to eliminate judder. This is used in conjunction with the -vsync parameter using the 1 option which will retime the PTS/DTS timestamps accordingly"
Section six – Audio [Has some good advice too]
"-af "aresample=async=1:min_hard_comp=0.100000:first_pts=0" helps to keep your audio lined up with the beginning of your video. It is common for a container to have the beginning of the video and the beginning of the audio start at different points. By using this your container should have little to no audio drift or offset as it will pad the audio with silence or trim audio with negative PTS timestamps if the audio does not actually start at the beginning of the video."
I haven't tried this yet, no videos with sync problems at the moment.

Wav audio file compression not working

Is it possible to compress a wav audio file without reducing the sampling rate?
I have an audio file with 256 bit rate and sampling rate - 8000Hz. I would just like to reduce the bit rate to 128/64 kbs
I tried converting to mp3 and back to wav,
ffmpeg -i input.wav 1.mp3
ffmpeg -i "1.mp3" -acodec pcm_s16le -ar 4000 out.wav
but this reduced sampling rate as well.
ffmpeg -i "1.mp3" -acodec pcm_s16le -ab 128 out.wav has default 256 bit rate
PCM (WAV) is uncompressed, so -b:a/-ab is ignored.
The bitrate of WAV is directly affected by the sample rate, channel layout, and bits per sample.
Calculating PCM/WAV bitrate
Assuming 8000 samples per second, stereo channel layout, 16 bits per sample:
sample rate × number of channels × bits per sample = bitrate
8000 × 2 × 16 = 256000 bits/s, or 256 kb/s
Getting channels, sample rate, bit depth
You can just view the output of ffmpeg -i input.wav or use ffprobe for a more concise output:
$ ffprobe -loglevel error -select_streams a -show_entries stream=sample_rate,channels,bits_per_sample -of default=nw=1 input.wav
sample_rate=8000
channels=2
bits_per_sample=16
Changing the bitrate
Bitrate should not be a consideration when using WAV. If bitrate is a problem then WAV is the wrong choice for you. That being said, you can change the bitrate by changing:
The sample rate (-ar)
The number of channels (-ac)
The bit depth. For PCM/WAV the bit depth is the number listed in the encoder name: -c:a pcm_s24le, -c:a pcm_s16le, -c:a pcm_u8, etc. See ffmpeg -encoders.
Examples for 128 kb/s (this will probably sound bad):
ffmpeg -i input.wav -ar 8000 -ac 1 -c:a pcm_s16le output.wav
ffmpeg -i input.wav -ar 8000 -ac 2 -c:a pcm_s8 output.wav
Another option is to use a lossless compressed format. The quality will be the same as WAV but the file size can be significantly smaller. Example for FLAC:
$ ffmpeg -i audio.wav audio.flac
$ ls -alh audio.wav audio.flac
6.1M audio.flac
11M audio.wac
I usually do this using Audacity
1) import the wav file to audacity
2) Then File>Export
3) Choose "Constant" and then from the Quality drop-down select your required bit-rate
I haven't tried that with ffmpeg, but the command should be:
ffmpeg -i input.wav -ab 64000 output.wav

What command convert mjpeg IP camera streaming to mp4 file with lowest CPU usage?

like above question, I want find out what ffmpeg command can help me reduce cpu usage when running 50 IP camera (running same 50 command).
My ffmpeg command:
ffmpeg -f mjpeg -y -use_wallclock_as_timestamps 1 -i 'http://x.x.x.x:8090/test1?.mjpg' -r 3 -reconnect 1 -loglevel 16 -c:v mjpeg -an -qscale 10 -copyts '1.mp4'
50 command like that take my computer (4 core) 200% CPU
I want this computer can run for 150 camera, any advise?
=========================================================
using -c:v copy can make it faster but fize size is terrible
I try slow down frame rate by 3 with -r 3 or -framerate 3 to decrease file size but not succesful (because vcodec copy can't do that).
Have any option to force input frame rate by 3?
(sorry for my bad English)
by setting -c:v mjpeg you are decoding and re-encoding the stream. set -c:v copy to copy the data without re-encoding it.
ffmpeg -re -i 'rtsp://user:password#10.10.10.30/rtsp_tunnel' -pix_fmt yuv420p -c:v libx264 -preset ultrafast -profile baseline -crf 18 -f h264 udp://0.0.0.0:3001

How can I place a still image before the first frame of a video?

When I encode videos by FFMpeg I would like to put a jpg image before the very first video frame, because when I embed the video on a webpage with "video" html5 tag, it shows the very first picture as a splash image. Alternatively I want to encode an image to an 1 frame video and concatenate it to my encoded video. I don't want to use the "poster" property of the "video" html5 element.
You can use the concat filter to do that. The exact command depends on how long you want your splash screen to be. I am pretty sure you don't want an 1-frame splash screen, which is about 1/25 to 1/30 seconds, depending on the video ;)
The Answer
First, you need to get the frame rate of the video. Try ffmpeg -i INPUT and find the tbr value. E.g.
$ ffmpeg -i a.mkv
ffmpeg version N-62860-g9173602 Copyright (c) 2000-2014 the FFmpeg developers
built on Apr 30 2014 21:42:15 with gcc 4.8 (Ubuntu 4.8.2-19ubuntu1)
[...]
Input #0, matroska,webm, from 'a.mkv':
Metadata:
ENCODER : Lavf55.37.101
Duration: 00:00:10.08, start: 0.080000, bitrate: 23 kb/s
Stream #0:0: Video: h264 (High 4:4:4 Predictive), yuv444p, 320x240 [SAR 1:1 DAR 4:3], 25 fps, 25 tbr, 1k tbn, 50 tbc (default)
At least one output file must be specified
In the above example, it shows 25 tbr. Remember this number.
Second, you need to concatenate the image with the video. Try this command:
ffmpeg -loop 1 -framerate FPS -t SECONDS -i IMAGE \
-t SECONDS -f lavfi -i aevalsrc=0 \
-i INPUTVIDEO \
-filter_complex '[0:0] [1:0] [2:0] [2:1] concat=n=2:v=1:a=1' \
[OPTIONS] OUTPUT
If your video doesn't have audio, try this:
ffmpeg -loop 1 -framerate FPS -t SECONDS -i IMAGE \
-i INPUTVIDEO \
-filter_complex '[0:0] [1:0] concat=n=2:v=1:a=0' \
[OPTIONS] OUTPUT
FPS = tbr value got from step 1
SECONDS = duration you want the image to be shown.
IMAGE = the image name
INPUTVIDEO = the original video name
[OPTIONS] = optional encoding parameters (such as -vcodec libx264 or -b:a 160k)
OUTPUT = the output video file name
How Does This Work?
Let's split the command line I used:
-loop 1 -framerate FPS -t SECONDS -i IMAGE: this basically means: open the image, and loop over it to make it a video with SECONDS seconds with FPS frames per second. The reason you need it to have the same FPS as the input video is because the concat filter we will use later has a restriction on it.
-t SECONDS -f lavfi -i aevalsrc=0: this means: generate silence for SECONDS (0 means silence). You need silence to fill up the time for the splash image. This isn't needed if the original video doesn't have audio.
-i INPUTVIDEO: open the video itself.
-filter_complex '[0:0] [1:0] [2:0] [2:1] concat=n=2:v=1:a=1': this is the best part. You open file 0 stream 0 (the image-video), file 1 stream 0 (the silence audio), file 2 streams 0 and 1 (the real input audio and video), and concatenate them together. The options n, v, and a mean that there are 2 segments, 1 output video, and 1 output audio.
[OPTIONS] OUTPUT: this just means to encode the video to the output file name. If you are using HTML5 streaming, you'd probably want to use -c:v libx264 -crf 23 -c:a libfdk_aac (or -c:a libfaac) -b:a 128k for H.264 video and AAC audio.
Further information
You can check out the documentation for the image2 demuxer which is the core of the magic behind -loop 1.
Documentation for concat filter is also helpful.
Another good source of information is the FFmpeg wiki on concatenation.
The answer above works for me but in my case it took too much time to execute (perhaps because it re-encodes the entire video). I found another solution that's much faster. The basic idea is:
Create a "video" that only has the image.
Concatenate the above video with the original one, without re-encoding.
Create a video that only has the image:
ffmpeg -loop 1 -framerate 30 -i image.jpg -c:v libx264 -t 3 -pix_fmt yuv420p image.mp4
Note the -framerate 30 option. It has to be the same with the main video. Also, the image should have the same dimension with the main video. The -t 3 specifies the length of the video in seconds.
Convert the videos to MPEG-2 transport stream
According to the ffmpeg official documentation, only certain files can be concatenated using the concat protocal, this includes the MPEG-2 transport streams. And since we have 2 MP4 videos, they can be losslessly converted to MPEG-2 TS:
ffmpeg -i image.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts image.ts
and for the main video:
ffmpeg -i video.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts video.ts
Concatenate the MPEG-2 TS files
Now use the following command to concatenate the above intermediate files:
ffmpeg -i "concat:image.ts|video.ts" -c copy -bsf:a aac_adtstoasc output.mp4
Although there are 4 commands to run, combined they're still much faster then re-encoding the entire video.
My solution. It sets an image with duration of 5 sec before the video along with aligning video to be 1280x720. Image should have 16/9 aspect ratio.
ffmpeg -i video.mp4 -i image.png -filter_complex '
color=c=black:size=1280x720 [temp]; \
[temp][1:v] overlay=x=0:y=0:enable='between(t,0,5)' [temp]; \
[0:v] setpts=PTS+5/TB, scale=1280x720:force_original_aspect_ratio=decrease, pad=1280:720:-1:-1:color=black [v:0]; \
[temp][v:0] overlay=x=0:y=0:shortest=1:enable='gt(t,5)' [v]; \
[0:a] asetpts=PTS+5/TB [a]'
-map [v] -map [a] -preset veryfast output.mp4

FFmpeg ignores quantity parameter

this is how I use FFmpeg
ffmpeg -f dshow -i video="UScreenCapture" -vcodec libx264 -q 26 -f flv output.flv
the thing is, the quantity is always 28, ffmpeg ignores that. How to fix this? I need a "flash" codec anyway, to stream to twitch tv
The options -q (and the alias -qscale) are ignored by libx264. If you want to
control the quality,
use:
-crf
ffmpeg -i input -c:v libx264 -crf 22 output.flv
Or set the bitrate with -b:v
ffmpeg -i input -c:v libx264 -b:v 555k output.flv
According to the documentation, "the meaning of q is codec-dependent" and apparently libx264 ignores that option. Use -crf (and a -preset if you want) instead. The bigger the crf value, the lower the quality.
if you wish to generate CQP (constant QP stream), e.g for constant QP=20 i suggest using the following parameters:
'x264-params qp=20:ipratio=1.0:pbratio=1.0:qpstep=0'
Example:
ffmpeg -s 1920x1080 -i test.yuv -vcodec libx264 -x264-params qp=20:ipratio=1.0:pbratio=1.0:qpstep=0 -y test.h264
Notice that 'ipratio=1.0' makes x264 to encode P frame with same QP as I-frame and 'pbratio=1.0' makes x264 to encode B-frame with same QP as P-frame.
The -b options, -q, and -crf seem to do nothing for video qualtiy (at least for my install of ffmpeg version 9), so I am posting a result from another post that gets right to the point
If you want high quality, setting bitrate is a poor way to achieve that. There are many other settings with far bigger influence on quality than bitrate. I would leave the bitrate setting out entirely unless you are having to meet hardware requirements of some sort.
If you are trying to get higher quality, try something like
ffmpeg -i sourcefile.mov -target pal-dvd -qscale 2 -trellis 2 outputfile.mpg
output video size goes from 13Mb for a 2 min video to 130Mb, but it gets the job done.

Resources