Привіт, мені потрібно витягти кадри з відео, використовуючи ffmpeg .. Чи є більш швидкий спосіб зробити це:
ffmpeg -i file.mpg -r 1/1 $filename%03d.jpg
?
parallel -i {} -r 1/1 {.}-%03d.bmp ::: *mpg
Привіт, мені потрібно витягти кадри з відео, використовуючи ffmpeg .. Чи є більш швидкий спосіб зробити це:
ffmpeg -i file.mpg -r 1/1 $filename%03d.jpg
?
parallel -i {} -r 1/1 {.}-%03d.bmp ::: *mpg
Відповіді:
Якщо крок кодування JPEG занадто інтенсивний, ви завжди можете зберігати кадри, нестиснуті як зображення BMP:
ffmpeg -i file.mpg -r 1/1 $filename%03d.bmp
Це також має перевагу в тому, щоб не зазнавати більших втрат якості через квантування шляхом перекодування в JPEG. (PNG також без втрат, але, як правило, займає набагато більше часу, ніж JPEG для кодування.)
ffmpeg -r 1 file.mp4 -r 1 "$filename%03d.png"
ffmpeg -r 1 -i file.mp4 -r 1 "$filename%03d.png
, правда? (ви пропустили -i
)
Я зіткнувся з цим питанням, тому ось коротке порівняння. Порівняйте ці два різні способи витягування одного кадру в хвилину з відео довжиною 38м07:
time ffmpeg -i input.mp4 -filter:v fps=fps=1/60 ffmpeg_%0d.bmp
1м36.029с
Це займе багато часу, оскільки ffmpeg аналізує весь відеофайл, щоб отримати потрібні кадри.
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м4.689с
Це приблизно в 20 разів швидше. Ми використовуємо швидку прагнення перейти до потрібного індексу часу і витягнути кадр, а потім викликаємо ffmpeg кілька разів для кожного індексу часу. Зверніть увагу, що -accurate_seek
це за замовчуванням
, і переконайтеся, що ви додали -ss
перед -i
опцією вхідного відео .
Зауважте, що краще використовувати -filter:v -fps=fps=...
замість того -r
, що останні можуть бути неточними. Незважаючи на те, що квиток позначений як фіксований , я все-таки відчув деякі проблеми, тож краще зіграйте в безпеці.
bc
не є рідним пакетом Ubuntu, натомість можна використовувати bash : let "i = $i * 60"
. BTW - відмінна ідея
-ss
раніше -i
. В іншому випадку все відео буде декодовано, а непотрібні кадри будуть відкинуті
ffmpeg
на ядро вашого хоста - що (для bmp) дає майже лінійне поліпшення швидкості (поки ви не потрапите на якесь інше вузьке місце, наприклад, диск).
Якщо ви точно знаєте, які кадри витягти, наприклад, 1, 200, 400, 600, 800, 1000, спробуйте скористатися:
select='eq(n\,1)+eq(n\,200)+eq(n\,400)+eq(n\,600)+eq(n\,800)+eq(n\,1000)' \
-vsync vfr -q:v 2
Я використовую це з трубою для монтажу Imagemagick, щоб отримати 10 кадрів попереднього перегляду з будь-якого відео. Очевидно, номери кадрів вам потрібно буде з'ясувати, використовуючиffprobe
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
.
Невелике пояснення:
+
означає "АБО" і " *
І"\,
просто втеча від ,
персонажа-vsync vfr -q:v 2
нього це, здається, не працює, але я не знаю, чому - хтось?Я спробував це. 3600 кадрів за 32 секунди. ваш метод справді повільний. Ви повинні спробувати це.
ffmpeg -i file.mpg -s 240x135 -vf fps=1 %d.jpg
ffmpeg -i "input URL" -vf fps=1/5 out%d.png
де вхідною URL-адресою має бути https-посилання.
ffmpeg -i file.mpg -vf fps=1 %d.jpg
У моєму випадку мені потрібні кадри щонайменше щосекунди. Я використовував підхід "прагнути" вище, але цікавився, чи зможу я паралельно поставити завдання. Я використав N процесів із FIFO підходом тут: /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
По суті, я розв'язав процес з &, але обмежив кількість одночасних потоків до N.
Це покращило підхід "прагнення до" з 26 секунд до 16 секунд у моєму випадку. Єдина проблема полягає в тому, що головний потік не виходить чисто назад до терміналу, оскільки stdout затоплюється.
Це працювало для мене
ffmpeg -i file.mp4 -vf fps=1 %d.jpg