如何基于分辨率变化自动拆分flv/mp4视频文件?
Hey there! I’ve got a straightforward, no-re-encoding solution to split your FLV/MP4 videos whenever the resolution changes—perfect for preserving that original quality you care about. Here’s how to make it happen step by step:
Step 1: Extract Resolution Change Timestamps
First, we’ll use ffprobe (included with FFmpeg) to pull frame-level data that tracks exactly when the video width shifts. Run this command on your input video:
ffprobe -v error -select_streams v:0 -show_entries frame=pkt_pts_time,width -of csv=p=0 input.mp4 > resolution_changes.txt
-v error: Cuts down on unnecessary log noise so we only get useful data-select_streams v:0: Targets the first video stream (adjust if your video has multiple streams)-show_entries frame=pkt_pts_time,width: Grabs the timestamp (in seconds) and pixel width of every frame-of csv=p=0: Outputs data in a clean, header-free CSV format that’s easy to process
This creates a resolution_changes.txt file with lines like 12.345,1920 (timestamp, width).
Step 2: Flag Split Points
Next, use a simple bash script to scan the resolution data and note timestamps where the width changes. Save this as find_split_points.sh:
#!/bin/bash prev_width="" while read -r time width; do if [ -n "$prev_width" ] && [ "$width" != "$prev_width" ]; then echo "$time" fi prev_width="$width" done < resolution_changes.txt > split_points.txt
Make it executable and run it:
chmod +x find_split_points.sh ./find_split_points.sh
This generates split_points.txt with all the timestamps where the resolution switches.
Step 3: Split the Video (No Re-Encoding)
Finally, use FFmpeg’s stream copy mode (-c copy) to split the video at our detected timestamps. Save this as split_video.sh:
#!/bin/bash input_file="input.mp4" start_time=0 segment_num=1 # Add the total video duration to capture the final segment total_duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$input_file") echo "$total_duration" >> split_points.txt # Loop through split points and create segments while read -r end_time; do output_file="${input_file%.*}-scene$segment_num.${input_file##*.}" ffmpeg -i "$input_file" -ss "$start_time" -to "$end_time" -c copy "$output_file" start_time="$end_time" segment_num=$((segment_num + 1)) done < split_points.txt
Adjust input_file to match your video’s filename, make the script executable, and run it:
chmod +x split_video.sh ./split_video.sh
Quick Tips:
- 100% Quality Retention: The
-c copyflag copies original video/audio streams directly—no re-encoding means no quality loss and fast processing. - FLV/MP4 Compatibility: This works seamlessly for both formats since FFmpeg supports stream copying for both.
- Key Frame Safety: FFmpeg automatically snaps to the nearest key frame when splitting, so you won’t get corrupted segments even if the split timestamp falls between frames.
- Batch Processing: To handle multiple videos, wrap these steps in an extra loop that iterates over all your FLV/MP4 files.
内容的提问来源于stack exchange,提问作者EverT

