ffmpeg: удаление частей с тишиной: эффективно удалите несколько частей видео

Я пытаюсь удалить части видео, где нет (или мало) звука. Для этого я использую audacity ( анализ - >Sound finder) и экспортировать Метка Track. Это приводит к чему-то вроде этого:

0.000000    5.170000    1
12.520000   12.630000   2
14.400000   15.660000   3
17.430000   22.150000   4
...

С этим регулярным выражением:([d]+.[d]{6})t([d]+.[d]{6})t([d]+)n > ffmpeg -i VL1.mp4 -strict -2 -ss -to buff.mp4nffmpeg -f concat -i <(echo "file '/home/rene/videotest/output.mp4'nfile '/home/rene/videotest/buff.mp4'") -c copy output2.mp4nrm buff.mp4nmv output2.mp4 output.mp4n и некоторые ручного редактирования я получаю это:

#!/bin/bash

ffmpeg -i VL1.mp4 -strict -2 -ss 0.000000 -to 5.170000 output.mp4
ffmpeg -i VL1.mp4 -strict -2 -ss 12.520000 -to 12.630000 buff.mp4
ffmpeg -f concat -i <(echo "file '/home/rene/videotest/output.mp4'
file '/home/rene/videotest/buff.mp4'") -c copy output2.mp4
rm buff.mp4
mv output2.mp4 output.mp4
ffmpeg -i VL1.mp4 -strict -2 -ss 14.400000 -to 15.660000 buff.mp4
ffmpeg -f concat -i <(echo "file '/home/rene/videotest/output.mp4'
file '/home/rene/videotest/buff.mp4'") -c copy output2.mp4
rm buff.mp4
mv output2.mp4 output.mp4
ffmpeg -i VL1.mp4 -strict -2 -ss 17.430000 -to 22.150000 buff.mp4
ffmpeg -f concat -i <(echo "file '/home/rene/videotest/output.mp4'
file '/home/rene/videotest/buff.mp4'") -c copy output2.mp4
rm buff.mp4
mv output2.mp4 output.mp4
...

это работает довольно хорошо, и я получаю файл output.mp4 , который содержит только те части, которые я хочу.

к сожалению, это невероятно медленно, и я боюсь, что это разрушит мой жесткий диск (так как для каждой части есть файл buff.mp4 создан, новый файл, содержащий все существующие части плюс этот короткий клип записывается на жесткий диск и старый файл, содержащий существующие части удаляется). Поскольку большинство клипов очень короткие (обычно менее нескольких секунд) моя идея заключалась в том, чтобы не писать в файл buff.mp4 на жесткий диск, но вместо этого передать это в ffmpeg через < (так держать в оперативной памяти?). Второе, что нужно было добавить к output.mp4 и не рерайт файл каждый раз.

к сожалению, для обеих вещей мои знания о ffmpeg и bash в целом слишком тонкие. Кто-нибудь может мне помочь?

Я должен быть в состоянии написать хороший сценарий без ручного регулярное вещи. И, конечно, я опубликую это позже.

5
задан 3244611user
15.11.2022 6:32 Количество просмотров материала 2570
Распечатать страницу

1 ответ

решение, которое я использую сейчас, сканирует list-input-file и создает небольшие файлы с фрагментами "no-silence" из этой информации. Все файлы записываются в файл temp в правильном порядке. Когда это будет сделано, части будут объединены и временные файлы будут очищены. Это не очень быстро. В общей сложности около 1000 сокращений в 90-минутный клип занимает около 5 часов на процессоре i7, 10 ГБ оперативной памяти.

Я думаю решение с фильтрами ffmpeg это было бы намного быстрее. Но это было слишком сложно на данный момент. Другим решением может быть это код-пример. Оба, вероятно, будут более эффективными, потому что они не создают tmp-файлы (с заголовками, записью файлов и т. д.).

В общем, вот рабочий код в его текущем состоянии:

#!/bin/bash
echo "">temp

# File or Directory selection menu with dialog
function fileDialog {
    read -p ": " fileselection
    echo "You've selected $fileselection"
}


WORKPATH=$(pwd)

echo "Arbeitsverzeichnis: $WORKPATH"

fileDialog "$WORKPATH" "Select original Video-File"
INFILE=$fileselection
ff=$(ffmpeg -i "$INFILE" 2>&1)
d="${ff#*Duration: }"
LENGTH="${d%%,*}"
echo "Arbeitsverzeichnis: $WORKPATH"
echo "Videodatei: $INFILE"
echo "Gesamtvideolänge $LENGTH"

fileDialog "$WORKPATH" "Select Label-List-File (exported from Audacity)"
LABELFILE=$fileselection
NUMLINES=$(awk 'END { print NR }' "$LABELFILE")
clear
echo "Arbeitsverzeichnis: $WORKPATH"
echo "Videodatei: $INFILE"
echo "Gesamtvideolänge $LENGTH"
echo "Sequence-Label-Datei: $LABELFILE"
echo $NUMLINES lines/sequences found in \'$LABELFILE\'
echo ""
echo "Start processing..."
awk '{d=sprintf("echo Processing Part "NR"/'"$NUMLINES"' named "" from ""s to ""s..."); system(d); s=sprintf("ffmpeg -hide_banner -loglevel panic -accurate_seek -y -i '"$INFILE"' -strict -2 -ss "" -to "" tmp-"NR".mp4>/dev/null"); system(s); p=sprintf("echo \"$(cat temp)\nfile '"$WORKPATH"'/tmp-"NR".mp4\">temp"); system(p);}' "$LABELFILE"

echo "Merging all "$NUMLINES" parts."
ffmpeg -f concat -i temp -c copy "short-$INFILE.mp4"

echo "Cleaning up..."
rm tmp-*.mp4
rm temp
rm "$INFILE"

еще две маленькие вещи, которые нужно сделать: в настоящее время это преобразует ваше видео в mp4. Это не является действительно необходимым и, вероятно, требует только нагрузки процессора время.

0
отвечен 3244611user 2022-11-16 14:20

Постоянная ссылка на данную страницу: [ Скопировать ссылку | Сгенерировать QR-код ]

Ваш ответ

Опубликуйте как Гость или авторизуйтесь

Имя
Вверх