Xin chào, tôi cần trích xuất khung hình từ video bằng ffmpeg .. Có cách nào nhanh hơn để thực hiện việc này không:
ffmpeg -i file.mpg -r 1/1 $filename%03d.jpg
?
parallel -i {} -r 1/1 {.}-%03d.bmp ::: *mpg
Xin chào, tôi cần trích xuất khung hình từ video bằng ffmpeg .. Có cách nào nhanh hơn để thực hiện việc này không:
ffmpeg -i file.mpg -r 1/1 $filename%03d.jpg
?
parallel -i {} -r 1/1 {.}-%03d.bmp ::: *mpg
Câu trả lời:
Nếu bước mã hóa JPEG quá chuyên sâu về hiệu suất, bạn luôn có thể lưu trữ các khung hình không nén dưới dạng ảnh BMP:
ffmpeg -i file.mpg -r 1/1 $filename%03d.bmp
Điều này cũng có lợi thế là không làm giảm chất lượng nhiều hơn thông qua lượng tử hóa bằng cách chuyển mã sang JPEG. (PNG cũng không mất dữ liệu nhưng có xu hướng mất nhiều thời gian hơn JPEG để mã hóa.)
ffmpeg -r 1 file.mp4 -r 1 "$filename%03d.png"
ffmpeg -r 1 -i file.mp4 -r 1 "$filename%03d.png
, phải không? (bạn đã bỏ lỡ -i
)
Gặp phải câu hỏi này, vì vậy đây là một so sánh nhanh. So sánh hai cách khác nhau này để trích xuất một khung hình mỗi phút từ video dài 38m07 giây:
time ffmpeg -i input.mp4 -filter:v fps=fps=1/60 ffmpeg_%0d.bmp
1m36.029 giây
Quá trình này mất nhiều thời gian vì ffmpeg phân tích cú pháp toàn bộ tệp video để có được các khung hình mong muốn.
time for i in {0..39} ; do ffmpeg -accurate_seek -ss `echo $i*60.0 | bc` -i input.mp4 -frames:v 1 period_down_$i.bmp ; done
0 phút4,689 giây
Điều này nhanh hơn khoảng 20 lần. Chúng tôi sử dụng tính năng tìm kiếm nhanh để đi đến chỉ mục thời gian mong muốn và trích xuất một khung, sau đó gọi ffmpeg nhiều lần cho mỗi chỉ mục thời gian. Lưu ý rằng đó -accurate_seek
là mặc định
và đảm bảo bạn thêm -ss
trước -i
tùy chọn video đầu vào .
Lưu ý rằng nó tốt hơn để sử dụng -filter:v -fps=fps=...
thay vì -r
như sau này có thể không chính xác. Mặc dù vé được đánh dấu là đã sửa , tôi vẫn gặp một số vấn đề, vì vậy tốt hơn hãy chơi nó an toàn.
bc
không phải là một gói phần mềm Ubuntu bản xứ, thay vào đó người ta có thể sử dụng bash: let "i = $i * 60"
. BTW - ý tưởng tuyệt vời
-ss
trước -i
. Nếu không, toàn bộ video sẽ được giải mã và các khung unrequired sẽ bị loại bỏ
ffmpeg
trên mỗi lõi của máy chủ lưu trữ của bạn - điều này (đối với bmp) mang lại những cải thiện gần như tuyến tính về tốc độ (cho đến khi bạn gặp phải một số nút cổ chai khác, như đĩa).
Nếu bạn biết chính xác khung nào cần trích xuất, ví dụ: 1, 200, 400, 600, 800, 1000, hãy thử sử dụng:
select='eq(n\,1)+eq(n\,200)+eq(n\,400)+eq(n\,600)+eq(n\,800)+eq(n\,1000)' \
-vsync vfr -q:v 2
Tôi đang sử dụng cái này với một đường ống để dựng phim Imagemagick để có được 10 khung hình xem trước từ bất kỳ video nào. Rõ ràng là số khung bạn sẽ cần tìm ra bằng cách sử dụngffprobe
ffmpeg -i myVideo.mov -vf \
select='eq(n\,1)+eq(n\,200)+eq(n\,400)+eq(n\,600)+eq(n\,800)+eq(n\,1000)',scale=320:-1 \
-vsync vfr -q:v 2 -f image2pipe -vcodec ppm - \
| montage -tile x1 -geometry "1x1+0+0<" -quality 100 -frame 1 - output.png
.
Giải thích nhỏ:
+
là viết tắt của OR và *
AND\,
chỉ đơn giản là thoát khỏi ,
nhân vật-vsync vfr -q:v 2
nó dường như không hoạt động nhưng tôi không biết tại sao - có ai không?Tôi đã thử nó. 3600 khung hình trong 32 giây. phương pháp của bạn thực sự chậm. Bạn nên thử điều này.
ffmpeg -i file.mpg -s 240x135 -vf fps=1 %d.jpg
ffmpeg -i "input URL" -vf fps=1/5 out%d.png
URL đầu vào phải là liên kết https.
ffmpeg -i file.mpg -vf fps=1 %d.jpg
Trong trường hợp của tôi, tôi cần khung hình ít nhất mỗi giây. Tôi đã sử dụng cách tiếp cận 'seek to' ở trên nhưng tự hỏi liệu tôi có thể thực hiện song song nhiệm vụ không. Tôi đã sử dụng N quy trình với phương pháp FIFO tại đây: /unix/103920/parallelize-a-bash-for-loop/216475#216475
open_sem(){
mkfifo /tmp/pipe-$$
exec 3<>/tmp/pipe-$$
rm /tmp/pipe-$$
local i=$1
for((;i>0;i--)); do
printf %s 000 >&3
done
}
run_with_lock(){
local x
read -u 3 -n 3 x && ((0==x)) || exit $x
(
"$@"
printf '%.3d' $? >&3
)&
}
N=16
open_sem $N
time for i in {0..39} ; do run_with_lock ffmpeg -ss `echo $i` -i /tmp/input/GOPR1456.MP4 -frames:v 1 /tmp/output/period_down_$i.jpg & done
Về cơ bản, tôi đã tách quy trình với & nhưng giới hạn số luồng đồng thời đối với N.
Điều này đã cải thiện cách tiếp cận 'tìm kiếm' từ 26 giây xuống 16 giây trong trường hợp của tôi. Vấn đề duy nhất là luồng chính không thoát sạch trở lại thiết bị đầu cuối vì stdout bị ngập.
Điều này đã làm việc cho tôi
ffmpeg -i file.mp4 -vf fps=1 %d.jpg