ffmpeg извлекает фрагменты из видео в 10 секунд; 30%; 60%; последние 30 с видео - PullRequest
0 голосов
/ 01 июля 2018

Я пишу команду Bash на Mac-терминале. Чтобы иметь возможность использовать цикл, я хотел бы извлечь 4 субклипа из разных файлов .mp4 входного файла: 1-й субклип (со второго 10 до 20), 2-й субклип (10 секунд, начиная с 33% -ной стадии входного файла), 3-й субклип (10 секунд, начиная с 66% входного файла) и 4-й субклип (10 секунд, начинающихся за 30 секунд до конца входного файла).

Пока я знаю, как заставить его работать с фиксированными временами (то есть секундами), но они соответствуют только моему первому видео (у меня +200):

#!/bin/bash
for file in *.mp4; do ffmpeg -i "$file" -vf "select='between(t, 10, 20) + between(t, 197, 207) + between(t, 393, 403) + between(t, 570,580)',
setpts=N/FRAME_RATE/TB" -qscale 0 -af "aselect='between(t, 10, 20) + 
between(t, 197, 207) + between(t, 393, 403) + between(t, 570, 580)', 
asetpts=N/SR/TB" ${file%.mp4}_1.mp4; done

Для первого подклипа я всегда хочу от второго до 10, поэтому я могу оставить все как есть, но для 2-4-го подклипа мне нужны некоторые формулы, но я не знаю, какие именно. Есть предложения?

Спасибо за ваше время

1 Ответ

0 голосов
/ 02 июля 2018

Сначала вам нужно получить длительность видео в секундах:

DURATION=$(ffmpeg -i $file 2>&1 | grep "Duration" | awk '{print $2}' | sed 's/\..*//g' | awk '{split($1, a, ":"); print 3600*a[1] + 60*a[2] + a[3]}')

В этой команде вы запрашиваете у ffmpeg длительность видео и анализируете результат, выполняя поиск по ключевому слову «Duration» (grep), получая поле времени (awk), отбрасывая центсекунды (sed) и анализируя H: M. : S строка в количество секунд (awk).

Затем вы можете вычислить необходимые интервалы:

START1=10
END1=20
START2=$(($DURATION*33/100))
END2=$(($START2+10))
START3=$(($DURATION*66/100))
END3=$(($START3+10))
START4=$(($DURATION-30))
END4=$(($START4+10))

Вам нужны полные секунды, поэтому использовать подход bash, который возвращает целые числа, - хороший способ.

Вы должны убедиться, что ваше видео длится не менее 30 секунд.

Теперь вы можете запустить свою команду с правильными заменами времени:

#!/bin/bash

for file in *.mp4
do
    DURATION=$(ffmpeg -i $file 2>&1 | grep "Duration" | awk '{print $2}' | sed 's/\..*//g' | awk '{split($1, a, ":"); print 3600*a[1] + 60*a[2] + a[3]}')

    START1=10
    END1=20
    START2=$(($DURATION*33/100))
    END2=$(($START2+10))
    START3=$(($DURATION*66/100))
    END3=$(($START3+10))
    START4=$(($DURATION-30))
    END4=$(($START4+10))

    ffmpeg -i "$file" -vf "select='between(t, $START1, $END1) + between(t, $START2, $END2) + between(t, $START3, $END3) + between(t, $START4, $END4)', setpts=N/FRAME_RATE/TB" -qscale 0 -af "aselect='between(t, $START1, $END1) +  between(t, $START2, $END2) + between(t, $START3, $END3) + between(t, $START4, $END4)', asetpts=N/SR/TB" ${file%.mp4}_1.mp4
done
...