What FFmpeg Is and Why It Matters
FFmpeg is a free, open-source multimedia framework that can record, convert, and stream audio and video. It was started in 2000 by Fabrice Bellard and has been continuously developed since. It runs on Windows, macOS, Linux, and most other operating systems you are likely to encounter. It is command-line only, which scares people off initially, but the commands are actually pretty readable once you know the pattern.
Here is why it matters: FFmpeg is not just one tool. It is the engine inside virtually every video application you have ever used. VLC uses FFmpeg. Handbrake uses FFmpeg libraries. Plex uses FFmpeg for transcoding. YouTube itself processes video through an FFmpeg-based pipeline. When you use an online video converter, there is a very good chance an FFmpeg command is running on the server on your behalf. You are paying (with your data or subscription fee) for someone else's FFmpeg wrapper.
Learning to use FFmpeg directly gives you several things that wrappers cannot. Speed is the biggest one. FFmpeg stream copy (more on this below) is almost instantaneous for cutting operations because it does not re-encode the video at all. It just copies the relevant bytes. A 2-hour video cut to a 3-minute clip takes under two seconds on most modern hardware when using stream copy.
Control is the second benefit. You can specify exact codecs, bitrates, quality levels, container formats, audio channel mappings, subtitle stream handling, and dozens of other parameters. No GUI lets you do everything FFmpeg can do, because building a GUI for every FFmpeg option would be absurd. Some options simply do not exist in consumer tools.
Automation is the third benefit. FFmpeg is designed to be scripted. You can write a shell script or batch file that processes 50 videos overnight while you sleep. No clicking required. For anyone doing large-scale video processing, this is transformative.
The learning curve is front-loaded. The first time you write an FFmpeg command from memory, it takes a while. After that, the pattern clicks and you realize most cutting operations are variations of four or five core commands. That is what this guide covers.
Installing FFmpeg on Windows, Mac, and Linux
FFmpeg is not installed by default on any operating system. Here is the fastest installation path for each platform.
Windows
The cleanest option in 2026 is using Windows Package Manager (winget), which is built into Windows 10 and 11. Open PowerShell or Command Prompt and run:
winget install --id Gyan.FFmpeg
Alternatively, using Chocolatey (if you have it installed):
choco install ffmpeg
If you prefer manual installation: go to ffmpeg.org, click "Download," then "Windows builds from gyan.dev." Download the "release full" build as a zip file. Extract it somewhere permanent like C:\ffmpeg. Then add C:\ffmpeg\bin to your system PATH environment variable (search "environment variables" in the Start menu, edit the Path variable under System Variables, add the path). Close and reopen your terminal. Type ffmpeg -version to verify it worked.
macOS
Homebrew is the standard and easiest method:
brew install ffmpeg
This installs FFmpeg with most common codec support. If you need specific additional codecs (like libfdk_aac for high-quality AAC encoding), you can install the more complete version:
brew install ffmpeg --with-fdk-aac
After installation, ffmpeg -version in Terminal confirms success.
Linux
On Debian/Ubuntu-based systems:
sudo apt update
sudo apt install ffmpeg
On RHEL/Fedora/CentOS:
sudo dnf install ffmpeg
Or with yum on older systems:
sudo yum install ffmpeg
The package manager version may be slightly behind the latest FFmpeg release. For the absolute latest version on Ubuntu, you can add the official PPA before installing:
sudo add-apt-repository ppa:savoury1/ffmpeg4
sudo apt update
sudo apt install ffmpeg
After installation, verify with ffmpeg -version. The output shows the version number, build configuration, and enabled libraries. This is also useful for diagnosing codec availability issues later.
Stream Copy vs. Re-encode: The Core Tradeoff
Before writing a single command, you need to understand this distinction. Every FFmpeg cutting decision comes back to it.
Stream copy means FFmpeg takes the existing audio and video data and copies it directly into the new file without changing it. No encoding or decoding happens. This is extremely fast (often 100x or 200x real-time speed) and produces no quality loss because the data is not touched. The flag for this is -c copy or its equivalent -c:v copy -c:a copy.
The limitation of stream copy is that it can only cut at keyframe boundaries. Video files do not store every frame independently. They store keyframes (complete images) periodically, and between keyframes they store only the differences (delta frames). When you cut a video at a non-keyframe position using stream copy, FFmpeg has to snap to the nearest keyframe, which means your start and end times may be off by anywhere from a fraction of a second to several seconds, depending on the keyframe interval of the source video.
For most YouTube videos, keyframes occur every 2 to 4 seconds. So your cut might be off by up to 4 seconds at each end when using stream copy. For casual clips, this is usually fine. For precision work where you need a cut to happen at exactly 00:03:42.580, it is not fine.
Re-encoding means FFmpeg decodes the video into raw frames and then re-encodes those frames into the output file using the codec you specify. This is much slower (often real-time or slower for high-quality encoding), and it introduces some quality loss because you are encoding a lossy format from another lossy format. However, it can be perfectly frame-accurate because FFmpeg can decode to any exact frame and start encoding from there.
The choice: use stream copy when you need speed and do not care about being off by a second or two at the cut points. Use re-encoding when you need frame-accurate cuts, format conversion, or quality adjustment. Most casual video cutting uses stream copy. Subtitle burns, precise clip extractions, and format conversions require re-encoding.
Basic Cut Command
The simplest cut operation: start at a specific time, run for a specific duration. The command uses -ss for seek (start time) and -t for duration.
ffmpeg -i input.mp4 -ss 00:01:00 -t 00:00:30 -c copy output.mp4
Breaking this down:
-i input.mp4: the input file-ss 00:01:00: start position (1 minute into the video)-t 00:00:30: duration to include (30 seconds)-c copy: stream copy, no re-encodingoutput.mp4: the output file
This produces a 30-second clip starting from the 1-minute mark. Because we are using -c copy, FFmpeg will snap to the nearest keyframe. The actual start may be slightly before 1:00 and the end slightly off from 1:30. For most use cases, this does not matter.
Time format options FFmpeg accepts:
00:01:30(HH:MM:SS)00:01:30.500(HH:MM:SS.milliseconds)90(seconds as a plain number)90.5(seconds with decimal)
All of these work interchangeably. The HH:MM:SS format is easiest to read. The plain seconds format is easiest to calculate programmatically.
Cut by Start and End Time
Often you know exactly where you want the clip to start and end, not the duration. Use -to instead of -t:
ffmpeg -i input.mp4 -ss 00:01:00 -to 00:02:30 -c copy output.mp4
This takes everything from 1:00 to 2:30, producing a 90-second clip. Much more intuitive when you have identified specific timestamps in a video rather than calculating durations.
Note the important distinction: -t specifies a duration (how long to record), while -to specifies an end time (where to stop). Getting these mixed up produces clips of the wrong length. If you use -t 00:02:30 instead of -to 00:02:30, you will get a 2.5-minute clip starting at 1:00, not a 90-second clip ending at 2:30.
For clips from the beginning of the video, you can omit the -ss entirely:
ffmpeg -i input.mp4 -to 00:00:45 -c copy output.mp4
This takes the first 45 seconds.
For clips going to the end of the video from a start point, omit -to and -t:
ffmpeg -i input.mp4 -ss 00:45:00 -c copy output.mp4
This takes everything from 45:00 to the end of the video. Useful for trimming a long intro off a recording.
Frame-Accurate Cutting: Where to Put the -ss Flag
This is where most FFmpeg tutorials either skip the detail or explain it confusingly. The position of -ss in your command changes its behavior significantly.
Putting -ss before -i (input seeking): FFmpeg seeks to the approximate position before opening the file, then starts processing. This is fast because FFmpeg skips ahead in the file without reading it. However, it is only as accurate as the keyframe interval. You get speed, not precision.
ffmpeg -ss 00:01:00 -i input.mp4 -t 30 -c copy output.mp4
Putting -ss after -i (output seeking): FFmpeg opens the file from the beginning, decodes every frame up to the specified time, and then starts writing output from that exact frame. This is frame-accurate. It is also much slower for large files because FFmpeg has to read and decode everything before your start point.
ffmpeg -i input.mp4 -ss 00:01:00 -t 30 -c copy output.mp4
The practical recommendation: for stream copy operations (-c copy), always put -ss before -i for speed. The keyframe snapping limitation of stream copy makes the precision difference irrelevant anyway. For re-encoding operations (libx264, etc.), put -ss before -i for speed but understand you might be off by up to a keyframe. For truly frame-precise cuts, put -ss after -i and accept the slower processing.
A third hybrid approach (fastest + most precise for long files):
ffmpeg -ss 00:59:50 -i input.mp4 -ss 00:00:10 -t 30 -c:v libx264 -crf 18 -c:a copy output.mp4
The first -ss before -i fast-seeks to 10 seconds before your target. The second -ss after -i then decodes precisely the remaining 10 seconds to hit the exact frame. FFmpeg only needs to decode 10 seconds precisely instead of 60 minutes. This is the approach professionals use for long files where precision matters.
Re-encode for Frame Precision
When you need frame-accurate cuts, you re-encode. Here is the command that handles most video content well:
ffmpeg -ss 00:01:00 -i input.mp4 -t 30 -c:v libx264 -crf 21 -preset fast -c:a aac -b:a 192k output.mp4
Breaking this down:
-ss 00:01:00before-i: fast input seek-t 30: 30 seconds duration-c:v libx264: encode video with H.264-crf 21: quality level (18 = near-lossless, 28 = noticeable quality loss, 21 is a good default)-preset fast: encoding speed vs. compression tradeoff (ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow)-c:a aac: encode audio with AAC-b:a 192k: audio bitrate 192 kbps
The CRF (Constant Rate Factor) scale: lower numbers mean higher quality and larger files. 18 is near-lossless and visually indistinguishable from the original for most content. 23 is the libx264 default. 28 starts looking noticeably degraded on high-motion content. For clips you are going to upload to social media, CRF 21 to 23 is perfectly fine since the platform will re-encode your file anyway.
The preset affects encoding speed and compression efficiency, not quality. slow produces a smaller file at the same quality compared to fast, but takes longer. For a 30-second clip, the difference is negligible. For a 2-hour file, the slower preset can save hundreds of megabytes. Use fast for most work. Use slow when file size matters.
Hardware encoding (much faster on modern machines):
- NVIDIA GPU: replace
-c:v libx264with-c:v h264_nvenc -rc vbr -cq 21 - AMD GPU: replace with
-c:v h264_amf -quality balanced - Apple Silicon: replace with
-c:v h264_videotoolbox -q:v 65 - Intel QuickSync: replace with
-c:v h264_qsv -global_quality 21
Hardware encoding can be 5 to 20 times faster than software encoding, with comparable output quality for most content. The quality scale varies by encoder, so check the documentation for each.
Remove a Middle Section
This is the operation that trips people up because FFmpeg cannot do it in one pass directly. You have to cut two segments and then concatenate them. Here is the complete workflow.
Say you want to remove the section from 00:02:00 to 00:04:30 from a video, keeping everything before and after.
Step 1: Cut the first part (start to 2:00):
ffmpeg -i input.mp4 -to 00:02:00 -c copy part1.mp4
Step 2: Cut the second part (4:30 to end):
ffmpeg -ss 00:04:30 -i input.mp4 -c copy part2.mp4
Step 3: Create a text file listing the parts to concatenate. Create a file called concat.txt with this content:
file 'part1.mp4'
file 'part2.mp4'
Step 4: Concatenate using the concat demuxer:
ffmpeg -f concat -safe 0 -i concat.txt -c copy output.mp4
Step 5 (cleanup): delete the temporary files part1.mp4, part2.mp4, and concat.txt once you have verified the output.
The -safe 0 flag tells FFmpeg to allow file paths that are not "safe" (i.e., not relative paths within the current directory). Without it, absolute paths in concat.txt cause an error.
An important limitation: the concat demuxer works cleanly only when the input files have the same codec, resolution, frame rate, and audio format. Mixing stream-copied segments from the same source file satisfies this automatically. If you are concatenating files from different sources, you need to re-encode both parts to a common format first, or use the more complex concat filter instead of the concat demuxer.
Split Into Segments
FFmpeg can split a long video into fixed-duration segments automatically, without you specifying each cut manually. This is useful for splitting a long recording into 5-minute chunks, splitting a stream recording into episode-length parts, or creating segment files for HLS streaming.
Split into 5-minute (300 second) segments:
ffmpeg -i input.mp4 -c copy -f segment -segment_time 300 -reset_timestamps 1 out_%03d.mp4
Breaking this down:
-f segment: use the segment muxer output format-segment_time 300: target segment duration in seconds (300 = 5 minutes)-reset_timestamps 1: reset timestamps to start from 0 in each segment (without this, segment 2 starts at 5:00, segment 3 at 10:00, etc.)out_%03d.mp4: output naming pattern (%03d = zero-padded three-digit number: out_000.mp4, out_001.mp4, etc.)
The actual split points will be at keyframes, so segments may not be exactly 5 minutes. They will be approximately 5 minutes, cutting at the nearest keyframe to the 5-minute mark.
For guaranteed keyframe-aligned splits, combine with the -force_key_frames option during a prior encoding pass, or re-encode on the split command itself (replace -c copy with your encoder options). This gives exact splits but takes longer.
Segment file size limit instead of time limit:
ffmpeg -i input.mp4 -c copy -f segment -segment_size 100M -reset_timestamps 1 out_%03d.mp4
This splits at approximately 100 MB per segment. Useful when you need to fit files under an upload size limit.
Extract Audio Only
To get the audio track from a video file as an MP3:
ffmpeg -i input.mp4 -vn -c:a libmp3lame -q:a 2 output.mp3
-vn: no video (discard the video stream)-c:a libmp3lame: encode audio with the LAME MP3 encoder-q:a 2: variable bitrate quality level (0 = best, 9 = worst; 2 is roughly equivalent to 190 kbps and sounds excellent)
For a fixed bitrate MP3 instead of variable bitrate:
ffmpeg -i input.mp4 -vn -c:a libmp3lame -b:a 192k output.mp3
For the highest-quality, most compatible audio extraction (M4A/AAC, which is what YouTube actually uses internally):
ffmpeg -i input.mp4 -vn -c:a aac -b:a 256k output.m4a
To extract as WAV (uncompressed, lossless, large files):
ffmpeg -i input.mp4 -vn -c:a pcm_s16le output.wav
pcm_s16le means signed 16-bit little-endian PCM, which is standard CD-quality audio. Use pcm_s24le for 24-bit if the source has higher quality than CD.
To extract audio without re-encoding (just copy the existing audio stream, whatever format it is in):
ffmpeg -i input.mp4 -vn -c:a copy output.aac
This is the fastest option and preserves the original audio exactly. The output extension should match the actual codec in the file (use ffmpeg -i input.mp4 with no output to see what audio codec the file contains).
Convert Between Formats
Format conversion is one of FFmpeg's most common use cases. The commands follow the same pattern as cutting, just without the time flags.
WebM to MP4 (very common when downloading from browser-recorded content):
ffmpeg -i input.webm -c:v libx264 -crf 22 -c:a aac -b:a 192k output.mp4
MKV to MP4 (often the audio and video codecs are already compatible, so stream copy works):
ffmpeg -i input.mkv -c copy output.mp4
If this fails with a codec compatibility error, the MKV contains an audio format (like AC3 or DTS) that the MP4 container does not support. Re-encode the audio:
ffmpeg -i input.mkv -c:v copy -c:a aac -b:a 192k output.mp4
MOV to MP4 (common when working with footage from iOS or older Mac software):
ffmpeg -i input.mov -c copy output.mp4
AVI to MP4 (AVI files often contain older codecs that are not supported in MP4, so re-encode):
ffmpeg -i input.avi -c:v libx264 -crf 22 -c:a aac -b:a 192k output.mp4
Change resolution (downscale to 1080p from 4K):
ffmpeg -i input.mp4 -vf scale=1920:1080 -c:v libx264 -crf 22 -c:a copy output.mp4
Maintain aspect ratio when scaling (scale width to 1280, auto-calculate height):
ffmpeg -i input.mp4 -vf scale=1280:-2 -c:v libx264 -crf 22 -c:a copy output.mp4
The -2 tells FFmpeg to calculate the dimension automatically while keeping it divisible by 2 (required for most H.264 encoders). Using -1 instead skips the divisibility requirement but may cause encoding errors with some content.
Batch Processing
Processing multiple files automatically is where the command line truly outshines any GUI tool. Here are batch processing patterns for both Windows and Linux/Mac.
Windows (PowerShell)
Convert all AVI files in a folder to MP4:
Get-ChildItem -Filter "*.avi" | ForEach-Object {
ffmpeg -i $_.FullName -c:v libx264 -crf 22 -c:a aac -b:a 192k "$($_.BaseName).mp4"
}
Or using the simpler batch script (cmd.exe) approach:
for %f in (*.avi) do ffmpeg -i "%f" -c:v libx264 -crf 22 -c:a aac -b:a 192k "%~nf.mp4"
In a .bat file, double the percent signs:
for %%f in (*.avi) do ffmpeg -i "%%f" -c:v libx264 -crf 22 -c:a aac -b:a 192k "%%~nf.mp4"
Linux and macOS (Bash)
Convert all MKV files to MP4:
for f in *.mkv; do
ffmpeg -i "$f" -c copy "${f%.mkv}.mp4"
done
Extract audio from all MP4 files in a folder:
for f in *.mp4; do
ffmpeg -i "$f" -vn -c:a libmp3lame -q:a 2 "${f%.mp4}.mp3"
done
Batch cut: trim the first 30 seconds from every MP4 in a folder (useful for removing intros):
for f in *.mp4; do
ffmpeg -ss 30 -i "$f" -c copy "trimmed_${f}"
done
Run jobs in parallel (process 4 files simultaneously on a multi-core machine):
ls *.mkv | xargs -P 4 -I {} ffmpeg -i {} -c copy {}.mp4
The -P 4 flag tells xargs to run 4 parallel processes. Adjust based on your CPU core count. Running too many parallel FFmpeg jobs causes them to compete for CPU resources and can actually be slower than sequential processing.
Optimizing for Web Delivery
When you are encoding a video that will be served from a web server and played in a browser, two FFmpeg options matter for the viewing experience.
faststart: By default, the MP4 metadata (moov atom) is written at the end of the file. For web playback, the browser needs the metadata before it can start playing. Without faststart, the browser has to download the entire file before it can begin playing. With faststart, the metadata is moved to the beginning and playback can start immediately:
ffmpeg -i input.mp4 -c copy -movflags +faststart output.mp4
This makes a huge difference for large files on slower connections. It is essentially a free optimization that takes zero extra encoding time.
You can also apply faststart to your re-encoding commands by simply adding -movflags +faststart:
ffmpeg -ss 00:01:00 -i input.mp4 -t 30 -c:v libx264 -crf 21 -preset fast -c:a aac -b:a 192k -movflags +faststart output.mp4
Target bitrate for streaming: If you are serving video at a known maximum bandwidth (say, mobile users on cellular connections), you can cap the bitrate to ensure smooth playback:
ffmpeg -i input.mp4 -c:v libx264 -b:v 1500k -maxrate 1500k -bufsize 3000k -c:a aac -b:a 128k -movflags +faststart output.mp4
-b:v 1500k: target video bitrate 1.5 Mbps (suitable for 720p at 30fps)-maxrate 1500k: hard maximum bitrate-bufsize 3000k: buffer size (typically 2x the maxrate for smooth streaming)
Typical bitrate guidelines for web video:
- 480p at 30fps: 500 to 1000 kbps
- 720p at 30fps: 1500 to 2500 kbps
- 1080p at 30fps: 3000 to 6000 kbps
- 1080p at 60fps: 4500 to 9000 kbps
- 4K at 30fps: 15000 to 30000 kbps
Common Errors and How to Fix Them
FFmpeg error messages can be cryptic. Here are the ones you will encounter most often and what to do about them.
"Encoder libmp3lame not found" or similar codec not found errors. Your FFmpeg installation was compiled without support for that codec. On Windows with the Gyan build, most codecs are included. On Linux, you may have installed a stripped-down version. Solution: install the full-featured build. On Ubuntu, add the savoury1 PPA before installing. On Linux in general, compile from source with your required codecs enabled, or use a pre-built binary from ffmpeg.org.
Output has wrong duration or is shorter than expected. Almost always caused by inaccurate seeking with stream copy. The cut snapped to a keyframe and ended up shorter than you specified. Solution: use re-encoding (-c:v libx264) for precision, or put -ss after -i instead of before it.
Audio and video are out of sync in the output. This happens when stream copying a clip that starts at a non-keyframe position. The video snaps to the keyframe but the audio starts at the exact time, causing them to drift. Solutions: (1) re-encode instead of stream copy, (2) add -avoid_negative_ts make_zero to your command, or (3) ensure the segment start aligns with a keyframe by using a tool like FFprobe to find keyframe positions first.
"Invalid data found when processing input". The file is corrupted or the format is not what FFmpeg expects. Try adding -fflags +genpts before the output file name. If the file was partially downloaded or recorded, use -fflags +discardcorrupt to skip corrupt packets. Sometimes changing the output format from MP4 to MKV helps because MKV is more tolerant of stream issues.
Output video has no sound. The audio track was not included. Check whether your input actually has audio: run ffmpeg -i input.mp4 with no output and look for "Audio:" in the output. If audio is present, make sure you have not accidentally used -an (no audio) in your command. If using -c copy with an MP4 output, some audio codecs (like AC3) are not allowed in MP4 containers. Re-encode the audio to AAC.
"Height not divisible by 2" or width error during encoding. H.264 requires video dimensions to be divisible by 2. If you specified an odd number in a scale filter, add -vf scale=trunc(iw/2)*2:trunc(ih/2)*2 to round to the nearest even number, or use -2 in the scale filter as described above.
File size is unexpectedly large. You used -crf 0 (lossless) accidentally, or the output format is uncompressed. Check your command for typos. For reference: a 30-second 1080p video at CRF 23 should be roughly 5 to 30 MB depending on content complexity. A lossless encode of the same could be gigabytes.
When to Use FFmpeg vs. YTCut
FFmpeg and YTCut are not competing tools. They solve adjacent problems and are often used together in the same workflow. Here is when to use each.
Use FFmpeg when:
- You have local video files that you want to cut, convert, or process
- You need to automate processing of many files (batch jobs, cron tasks)
- You need format conversion (WebM to MP4, MKV to MP4, etc.)
- You need to remove a middle section from a video
- You need frame-accurate cuts with specific codec settings
- You are building a pipeline that includes video processing as a step
- You need to process files that are not publicly accessible on YouTube
Use YTCut when:
- Your source content is a YouTube video (you do not want to download the full video just to clip part of it)
- You want a clip in seconds without opening a terminal
- You need MP3 or MP4 output from a YouTube URL with no setup
- You are not comfortable with the command line
- You want a no-install, browser-based solution
- You are working on a different computer than your usual setup
The most common workflow where both appear together: use YTCut to cut and download the specific segments from YouTube that you need (fast, no full download), then use FFmpeg to batch-process, convert, or further edit those local clips. YTCut gets the content off YouTube cleanly. FFmpeg handles any post-processing on your local machine.
FFmpeg will never replace a browser-based tool for the "I just need this one YouTube clip right now" scenario. And YTCut will never replace FFmpeg for server-side automation or complex local file processing. Both have their place.
FAQ
Is FFmpeg free to use commercially?
FFmpeg itself is licensed under the LGPL or GPL depending on the build options (specifically which codecs are compiled in). The LGPL version allows commercial use. However, some codecs that FFmpeg can use (like certain patent-encumbered ones) have their own licensing terms. For most common use cases including H.264 and AAC, there are royalty-free options available. Check the specific codec license if you are building a commercial product.
How do I check what codecs my video file contains?
Run ffmpeg -i filename.mp4 with no output arguments. FFmpeg will print the container format and all stream information including codecs, resolution, frame rate, bitrate, and audio format, then exit with an error (because there is no output specified, which is expected and harmless).
My FFmpeg command takes forever. How do I speed it up?
First, check if you can use -c copy instead of re-encoding. Stream copy is orders of magnitude faster. If you must re-encode, use -preset ultrafast for H.264 (lower compression but much faster). If your hardware supports it, use GPU encoding (h264_nvenc, h264_amf, h264_videotoolbox) instead of software encoding (libx264). GPU encoding is often 10 to 20 times faster for high-resolution content.
Can FFmpeg process 4K video?
Yes, FFmpeg handles 4K, 8K, and higher resolutions without issue. Stream copy is fastest and works fine for 4K. Re-encoding 4K with software encoding is slow and CPU-intensive. GPU encoding (NVENC with H.265 or AV1 support) is the practical approach for 4K re-encoding on modern hardware.
How do I add subtitles to a video with FFmpeg?
To burn subtitles permanently into the video (hardcode): ffmpeg -i input.mp4 -vf subtitles=subs.srt output.mp4. To add subtitles as a soft track (user can toggle them): ffmpeg -i input.mp4 -i subs.srt -c copy -c:s mov_text output.mp4. Soft subtitles only work in containers that support subtitle tracks (MKV, MP4). The subtitle format must match what the container supports (mov_text for MP4, ass or srt for MKV).
Can FFmpeg fix a corrupted video file?
Sometimes. For partially downloaded files or recordings that crashed, try: ffmpeg -fflags +genpts+discardcorrupt -i corrupted.mp4 -c copy fixed.mp4. This tells FFmpeg to regenerate timestamps and skip corrupt packets. It does not always work, but it is worth trying before giving up on a file. For more severe corruption, specialized tools like Grau GmbH's Video Repair Tool are more effective.
What is the difference between -vcodec and -c:v?
They are identical. -vcodec is the older flag name, -c:v is the newer, more consistent syntax. Both set the video codec. Similarly, -acodec and -c:a are identical, and -scodec and -c:s are identical for subtitle streams. Modern FFmpeg documentation uses the -c:v style, and it is what you will find in current tutorials. Both work.