// ========================================================================== // // FFMPEG Notes // Authors: Digipotion // Updated: 2023-11-16 // ========================================================================== // I'm no master of FFMPEG, but I've learned a few things here and there that I think might help. Any or all of the info here could be totally wrong. This file does not rigidly conform to an 80-character width to ensure functionality of commands among all terminals. // -------------------------------------------------------------------------- // // Commands // -------------------------------------------------------------------------- // Extract audio from video - Command ffmpeg -i {INPUT_VIDEO_FILE} -vn -acodec copy {OUTPUT_AUDIO_FILE} - Example ffmpeg -i input.mp4 -vn -acodec copy output.aac Add black (or any color) frames to start of video You need to create a solid-color bitmap file that matches the video resolution. - Command ffmpeg -loop 1 -framerate {FPS} -t {DURATION} -i {BITMAP_FILE} -i {INPUT_VIDEO_FILE} -filter_complex "[0][1]concat=n=2:v=1:a=0" {OUTPUT_VIDEO_FILE} - Example ffmpeg -loop 1 -framerate 30 -t 1 -i black.bmp -i input.mp4 -filter_complex "[0][1]concat=n=2:v=1:a=0" output.mp4 Add fade - Command ffmpeg -i {INPUT_VIDEO_FILE} -vf "fade=t={DIRECTION}:st={STARTING_TIME}:d={DURATION}" -c:a copy {OUTPUT_VIDEO_FILE} - Example ffmpeg -i input.mp4 -vf "fade=t=in:st=1:d=1" -c:a copy output.mp4 Replace audio track - Command ffmpeg -i {INPUT_VIDEO_FILE} -i {REPLACEMENT_AUDIO_FILE} -c:v copy -map 0:v:0 -map 1:a:0 {OUTPUT_VIDEO_FILE} - Example ffmpeg -i input.mp4 -i newaudio.wav -c:v copy -map 0:v:0 -map 1:a:0 output.mp4 Combine GIF & audio files, pausing on last frame of GIF for 2 seconds, with fade in/out The scale filter is needed for the GIF, the tpad filter pauses the GIF on its last frame, the fade filters are obvious. - Command ffmpeg -i {INPUT_GIF_FILE} -i {INPUT_AUDIO_FILE} -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2, tpad=stop_mode=clone:stop_duration=2, fade=in:0:20, fade=t=out:st=3:d=1" {OUTPUT_VIDEO_FILE} - Example ffmpeg -i input.gif -i input.wav -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2, tpad=stop_mode=clone:stop_duration=2, fade=in:0:20, fade=t=out:st=3:d=1" output.mp4 Cut clip, re-encoding video to reset keyframes A higher CRF value will reduce the quality but also the file size. A slower preset will result in a smaller file size due to more optimized compression, but it'll take longer to encode the file (see this page for more information). I usually set the preset to ultrafast while I'm trying to get the timing of the clip correct, then use slow when ready to perform the final cut. - Command ffmpeg -i {INPUT_VIDEO_FILE} -ss {START_TIME} -t {CLIP_DURATION} -c:v libx264 -crf {QUALITY} -preset {COMPRESSION_RATE} -c:a aac {OUTPUT_VIDEO_FILE} - Example ffmpeg -i input.mp4 -ss 00:20:00.0 -t 00:01:30.0 -c:v libx264 -crf 18 -preset slow -c:a aac output.mp4 // -------------------------------------------------------------------------- // // Mapping Streams // -------------------------------------------------------------------------- // Let's say you want to cut a clip from a file which has 1 video track, 3 audio tracks (Eng, Jpn, Fre), and 3 subtitle tracks (Eng, Fre, Ara). You want to capture the video, the English/Japanese audio, and the English subtitle track. First, you need to use ffprobe.exe to check which tracks are which. You'll receive a detailed output with the metadata for each track in the file (which are called "streams"). Each stream has a brief descriptor, which indicates the stream number, the type of stream (audio, video, subtitle), and some other information such as the codec and/or resolution. A lot of information has been truncated below, but you might see something similar to this: Stream #0:0(ara): Subtitle: ass (default) * Stream #0:1: Video: hevc (Main 10)... Stream #0:2(fre): Audio: aac (LC)... * Stream #0:3(jpn): Audio: aac (LC)... * Stream #0:4(eng): Audio: aac (LC)... Stream #0:5(fre): Subtitle: ass * Stream #0:6(eng): Subtitle: subrip * Stream #0:7: Attachment: ttf You won't see the asterisks, though. I put those in to highlight which streams we want for this example (you'll see their indices in the command below). Note the TTF file as well, I'm pretty sure we'll want that, too. For this example, we'll simply make a copy of the video. To select the streams, we'll use the -map option. We need to specify it for each of the streams we identified when we probed the video file. ffmpeg -i input.mkv -c copy -map 0:1 -map 0:3 -map 0:4 -map 0:6 -map 0:7 output.mkv And that's it! Another quick thing to note: if you have multiple streams, and you want to copy them all, it generally doesn't if you don't map anything. Without any mapping, FFMPEG will only copy the first streams it finds (in this case, it'd just copy the Japanese audio stream, for example). But, if you want to preserve ALL of the streams, simply use -map 0 and it'll do so. // ========================================================================== // https://www.digipotion.net