Skip to content

MP4 Conversion

Table of contents:

  • Cut a movie part
  • Conversion
    • Explanation
  • (auto-)Crop a video -- Black borders removal
    • Detect crop values automatically
    • Test and apply crop
  • CBR, CRF, and Changing Resolution using FFmpeg
    • Creating a Constant BitRate (CBR) Video
    • Using the CRF option to set desired quality
    • Change the resolution of the video to 1280×720
    • Conclusion
  • Extract audio
    • Extract via mkvextract
  • Conversion to projo
  • FFMPEG flags
  • Slow down audio
  • Volume up and down

Cut a movie part

src: http://superuser.com/questions/138331/ddg#704118

Using ffmpeg to cut up video.

As other people mentioned, putting -ss before (much faster) or after (more accurate) the -i makes a big difference. The section "Fast And Accurate Seeking" on the ffmpeg seek page tells you how to get both, and I have used it, and it makes a big difference. Basically you put -ss before AND after the -i, just make sure to leave enough time before where you want to start cutting to have another key frame. Example: If you want to make a 1-minute clip, from 9min0sec to 10min 0sec in Video.mp4, you could do it both quickly and accurately using:

    ffmpeg -ss 00:08:00 -i Video.mp4 -ss 00:01:00 \
        -t 00:01:00 -c copy VideoClip.mp4

The first -ss seeks fast to (approximately) 8min0sec, and then the second -ss seeks accurately to 9min0sec, and the -t 00:01:00 takes out a 1min0sec clip.

Also note this important point from that page:

If you use -ss with -c:v copy, the resulting bitstream might end up being choppy, not playable, or out of sync with the audio stream, since ffmpeg is forced to only use/split on i-frames.

This means you need to re-encode the video, even if you want to just copy it, or risk it being choppy and out of sync. You could try just -c copy first, but if the video sucks you'll need to re-do it.

Conversion

src: https://video.stackexchange.com/questions/19590/convert-mp4-to-webm-without-quality-loss-with-ffmpeg

Convert mp4 to webm without quality loss with ffmpeg.

Use two-pass Constant Quality mode:¹

    ffmpeg  -i input.mp4  -b:v 0  -crf 30  -pass 1  -an -f webm -y /dev/null
    ffmpeg  -i input.mp4  -b:v 0  -crf 30  -pass 2  output.webm

Explanation

Setting the video bitrate to zero while also specifying the CRF (Constant Rate Factor) enables Constant Quality mode which targets a certain perceptual quality level. For VP9, the CRF can range from 0 (best quality) to 63 (smallest file size).

It is important to set the video bitrate to zero. If you do not specify a video bitrate, it defaults to something low which gets you Constrained Quality mode, where each frame has a maximum bitrate. While that can be useful for streaming, it reduces quality significantly as frames with a lot of motion will not have the bandwidth needed to look good.

Another part of the reason you’re losing quality is that webm (VP9) prefers to encode in two passes for best results. The first pass compiles statistics about the video which is then used in the second pass to make a smaller and higher quality video.

Please see the ffmpeg VP9 documentation if you’d like to learn more. A word about transcoding

By the way, in general, transcoding formats (taking a compressed video and recompressing it with a different codec) is a bad idea as you’ll not only add the normal errors from lossy video encoding, but you’ll waste bits in the new format trying to preserve the artifacts from the old.

If you mean "without quality loss" literally: the -lossless 1 option of ffmpeg’s VP9 encoder enables lossless quality mode, but with a potentially enormous increase in filesize.

All you need is this:

    ffmpeg  -i input.mp4  -lossless 1  output.webm

When I tried -lossless 1 on a low-quality mp4, the resulting webm was 100× larger, which was not accceptable to me. However, if your mp4 files are already very high quality, I expect the size difference will not be so great.

Footnote 1: If you're using Microsoft Windows instead of UNIX, change /dev/null to NUL.

(auto-)Crop a video -- Black borders removal

Source and more info: René Calles blog renevolution.com

Detect crop values automatically

src: https://superuser.com/questions/772795/is-it-possible-to-autocrop-black-borders-of-a-video-with-ffmpeg#772833

It is possible to automatically detect crop values with ffplay:

    fplay -i YourMovie.mp4 -vf "cropdetect=24:16:0"

    # cropdetect=limit:round:reset
    # 
    # limit = black threshold (default 24)
    # round = output resolution must be divisible to this
    # reset = after how many frames the detection process will start over

You will see the result in the text output, which can vary over time.

Test and apply crop

src: https://www.linuxuprising.com/2020/01/ffmpeg-how-to-crop-videos-with-examples.html

When you have the correct values in hand (or if you want to test them manually), ffplay can still be used for that:

    ffplay -filter:v "crop=w:h:x:y" input.mp4
    ffplay -vf       "crop=w:h:x:y" input.mp4

When you are happy with the result, you can start the actual cropping:

    ffmpeg -i YourMovie.mp4 -vf "crop=640:256:0:36" \
        YourCroppedMovie.mp4
  • The crop filter crop=W:H:X:Y means we're using the "crop" video filter, with 4 values:
  • w the width of the output video (so the width of the cropped region), which defaults to the input video width (input video width = iw, which is the same as in_w); out_w may also be used instead of w
  • h the height of the output video (the height of the cropped region), which defaults to the input video height (input video height = ih, with in_h being another notation for the same thing); out_h may also be used instead of h
  • x the horizontal position from where to begin cropping, starting from the left (with the absolute left margin being 0)
  • y the vertical position from where to begin cropping, starting from the top of the video (the absolute top being 0)

A few notes:

  • The filter will automatically center the crop if x and y are omitted, so x defaults to (iw-w)/2, and y to (ih-h)/2
  • There is also an optional keep_aspect option that you can set to 1 to force the output display aspect ratio to be the same of the input (example usage: "crop=100:100:0:0:keep_aspect=1"). This won't work with images, that's why you don't see a separate example with screenshot here
  • FFmpeg gets the original input video width (iw) and height (ih) values automatically, so you can perform mathematical operations using those values (e.g. iw/2 for half the input video width, or ih-100 to subtract 100 pixels from the input video height).

CBR, CRF, and Changing Resolution using FFmpeg

src: https://ottverse.com/cbr-crf-changing-resolution-using-ffmpeg/

In this article, we will go through the process of compressing a video using the H.264/AVC codec (libx264) and discuss the following:

  • Creating a Constant Bitrate (CBR) encoded video
  • Using the Constant Rate Factor (CRF) option to set desired quality
  • Change the resolution of the video to 1280x720 or 720p.

For this purpose, we would be using a sample video with a resolution = 1920x1080 that can be downloaded at this link.

Creating a Constant BitRate (CBR) Video

To understand CBR, we need to understand what is bitrate. Bitrate is the amount of information or data stored per second in any media file such as audio or video. In technical terms, it is the rate of the data output of an encoder. For example, 2200 kbps as a bitrate means that 2200 kilobits of data is stored per second. For a deeper discussion on bitrate, don’t miss this article on "bitrate vs. resolution".

If the bitrate is "constant" throughout a video, it is termed as a CBR video. However, it is not possible to have constant bitrate for all the frames because of the different frame types and encoding priorities. Hence, if the bitrate is constant over a pre-determined time-period, the video is called a CBR-encoded video.

In order to output a constant bitrate video, we would be using the following FFmpeg output options :

  • -b:v – Specifies the average target output bitrate of the video
  • -maxrate – Specifies the maximum bitrate tolerance
  • -minrate – Specifies the minimum bitrate tolerance
  • -bufsize – Specifies the rate control buffer size that helps to maintain the bitrate according to the values of b:v, maxrate and minrate

After this, we also need to specify the video encoder using the -c:v option. As mentioned earlier, we are going to use the libx264 encoder in all the three cases.

Let’s say, we need to have a CBR of 2200 kbps for our sample video. The FFmpeg command for the CBR conversion will be as follows :

    ffmpeg -i crowdrun.mp4 -b:v 2200k -maxrate 2200k \
        -minrate 2200k -bufsize 2200k \
        -c:v libx264 output.mp4

If we try to analyze the bitrate of the output file, we would see that the difference between the highs and the lows of the bitrates in the file is very less. Ideally in CBR mode, the bitrate should be perfectly constant during the entire video but that is the ideal case and is not possible to achieve with software encoders.

(Related: LCEVC vs. AVC - Incredible 28% Gain at 3x Speed.)

Using the CRF option to set desired quality

The Constant Rate Factor or CRF is an option available in the libx264 encoder to set our desired output quality. It enables us to specify a target value that maps to a specific quality by adjusting the bitrates automatically based on the input video.

This method is better if we want to have the same output quality for different kinds of input videos as FFmpeg would automatically adjust the bitrates based on the input video properties. On the other hand, the previous method will keep the same bitrate which will result in different output qualities for different inputs.

The CRF value ranges from 0 to 51 where:

  • 0 is lossless (best) with highest file size
  • 23 is the default
  • 51 is the poorest quality with lowest file size

With low CRF value, the bitrate and hence, the file size of the video will increase. So it is important to decide the value based on the user requirements.

Let’s say, we need a compressed output video with lesser file size, we can go with the value of 30. The FFmpeg command for this would be:

    ffmpeg -i crowdrun.mp4 -crf 30 -c:v libx264 output.mp4 

Change the resolution of the video to 1280×720

FFmpeg provides a huge set of filters for various purposes. One of them is the scale filter that helps to scale the input to any resolution.

The two parameters for this filter that we would be using are:

  • w : It specifies the output width of the video
  • h : It specifies the output height of the video

Here, we would also add the CRF parameter(discussed in the last point) to compress and reduce the file size of the output video.

The FFmpeg command for this would be:

    ffmpeg -i crowdrun.mp4 -vf scale=w=1280:h=720 -crf 30 -c:v libx264 output.mp4

Conclusion

In this article, we learned how to use FFmpeg to produce a CBR-encoded video, CRF-encoded video, and how to change the resolution of a file. These three operations are very important to any video compression system and we hope you are able to use them to further your video compression using FFmpeg.

Extract audio

    ffmpeg -i input.mp4 -map a -c copy test.mp4

Extract via mkvextract

    mkvinfo "$1" # identify the track number
    mkvextract "$1" tracks \
        0:video.mpg 2:audio-jpn.dda 4:subs-fr.ssa

Conversion to projo

    ffmpeg -i audio-jpn.dda -i video.mpg \
        -c:v libx264 -c:a libmp3lame \
        -vf subtitles=subs-fr.ssa \
        output.mpg

FFMPEG flags

All the flags for an input file must be used before the linked -i.
All the flags not part of an input files (after the last -i) target the output file.

It is important not to mix input and output arguments.

Input arguments:

  • -an: take no audio from this input file
  • -vn: take no video from this input file

Output arguments:

  • -c:v libx264: convert video to x264
  • -c:a libmp3lame: convert audio to MP3
  • -c:v copy: copy the video data as-is
  • -c:a copy: copy the audio data as-is

Slow down audio

It is possible to slow down the audio of a video while style keeping the same pitch, with a complex filter.

You need to use a correlated number for the speed and the pitch:

  • speed (tempo) = X
  • pitch = 1 / X

For instance, to slow down to 75% of the original speed, you would use:

  • 0.75 for the tempo
  • 1.33 for the pitch
    ffmpeg -i INPUT.EXT -filter_complex \
        "[0:a]atempo=0.75[a];[0:v]setpts=1.33*PTS[v]" \
        -map "[v]" -map "[a]" \
        OUTPUT.EXT

Volume up and down

You can increase or decrease the volume with a filter (here, 150%):

  • -filter:a "volume=1.5"