2009-06-30 39 views
8

Tôi đang tự hỏi làm thế nào để sử dụng FFMpeg để grap khung giữa của video. Tôi đã viết C# để lấy một khung tại một thời điểm nhất định (tức là kéo một khung ở giây thứ 3). Nhưng tôi vẫn chưa tìm ra cách tìm đoạn video giữa bằng cách sử dụng lệnh FFMpeg.Sử dụng FFMpeg để tải khung hình ở giữa?

Trả lời

8

Điều này có thể được đơn giản hóa, nhưng đây là một số mã PHP cũ mà tôi đã nói dối mà nên làm các thủ thuật. (Thêm vị trí để ffmpeg nếu nó không có trong đường dẫn của bạn)

$output = shell_exec("ffmpeg -i {$path}"); 
preg_match('/Duration: ([0-9]{2}):([0-9]{2}):([^ ,])+/', $output, $matches); 
$time = str_replace("Duration: ", "", $matches[0]); 
$time_breakdown = explode(":", $time); 
$total_seconds = round(($time_breakdown[0]*60*60) + ($time_breakdown[1]*60) + $time_breakdown[2]); 
shell_exec("ffmpeg -y -i {$path} -f mjpeg -vframes 1 -ss " . ($total_seconds/2) . " -s {$w}x{$h} {$output_filename}"); 
+0

Cảm ơn, Đó chỉ là những gì tôi đang tìm kiếm! –

+0

@Derek Gathright Vui lòng cho tôi chi tiết cơ bản để bắt đầu làm việc với ffmpeg. Vui lòng xem [câu hỏi] của tôi (http://stackoverflow.com/questions/10071408/how-to-get-frames-of-video-file-in-android). –

4

FFmpeg giúp bạn nhận được tốc độ khung hình và độ dài của video, vì vậy bạn có thể nhân với nhau và chia cho 2 để lấy số khung ở giữa.

tức là đối với video 30 giây chạy ở 15 khung hình/giây: 30 * 15 = 450/2 = 225, có nghĩa là bạn cần lấy khung thứ 225.

0

bash này hoạt động lệnh như một nét duyên dáng (thử nghiệm):

avconv -i 'in.mpg' -vcodec mjpeg -vframes 1 -an -f rawvideo -s 420x300 -ss avconv -i in.mpg 2>&1 | grep Duration | awk '{print $2}' | tr -d , | awk -F ':' '{print ($3+$2*60+$1*3600)/2}' out.jpg 
2

Ví dụ

Giả sử bạn đang sử dụng Linux bạn có thể sử dụng ffprobe để có thời lượng, bc để tính một nửa điểm, sau đó là ffmpeg để tạo khung:

eval "$(ffprobe -v error -of flat=s=_ -show_entries format=duration input.mp4)" 
ffmpeg -ss "$(echo "$format_duration/2" | bc)" -i input.mp4 -q:v 2 -frames:v 1 half.jpg 

này giúp loại bỏ bất kỳ nhu cầu sử dụng awk, tr, grep, sed vv

Ngoài ra, bạn có thể sử dụng select filter và loại bỏ bc, nhưng chọn lọc có thể chậm.

Một lưu ý về thời gian

Thời gian từ ffprobe có thể không chính xác nếu các tập tin bị hư hỏng hoặc cắt ngắn không đúng. Thời gian có thể được xác nhận bởi hoàn toàn giải mã đầu vào với ffmpeg sau đó ghi nhận time= trong dòng thứ hai-to-cuối cùng trong giao diện điều khiển đầu ra:

ffmpeg -i input -f null - 
… 
frame= 2600 fps=569 q=-0.0 Lsize=N/A time=00:01:48.50 bitrate=N/A 
video:244kB audio:20344kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown 
+0

Trên Windows/Cygwin tôi đã phải xử lý văn bản kludge xấu xí của đầu ra của eval/ffprobe để loại bỏ một cửa sổ dòng mới từ cuối $ format_duration: 'eval '$ (ffprobe -v error -of flat = s = _ -show_entries format = thời gian tmp.mp4) "' 'echo $ format_duration> tmp.txt' ' vang/2 >> tmp.txt' 'dos2unix tmp.txt' format_duration = '' tr -d '\ n'

+0

Có một bộ backticks xung quanh việc gán biến sau khi format_duration trong phần cuối của bình luận của tôi (được loại bỏ ở đây bằng cách phân tích cú pháp markdown). –

Các vấn đề liên quan