3

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

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 \1 -to \2 buff.mp4\nffmpeg -f concat -i <(echo "file '/home/rene/videotest/output.mp4'\nfile '/home/rene/videotest/buff.mp4'") -c copy output2.mp4\nrm buff.mp4\nmv output2.mp4 output.mp4\n и некоторые ручные изменения я получаю так:

#!/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 в целом слишком слабое. Может ли кто-нибудь помочь мне?

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

1 ответ1

0

Решение, которое я использую сейчас, сканирует файл ввода-списка и создает небольшие файлы с фрагментами «безмолвия» из этой информации. Все файлы записываются в файл temp в правильном порядке. Когда это будет сделано, части будут объединены, а временные файлы будут очищены. Это не очень быстро. В общей сложности около 1000 срезов за 90-минутный клип занимает около 5 часов на процессоре i7 и 10 ГБ ОЗУ.

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

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

#!/bin/bash
echo "">temp

# File or Directory selection menu with dialog
function fileDialog {
    read -p "$2: " 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 "$3" from "$1"s to "$2"s..."); system(d); s=sprintf("ffmpeg -hide_banner -loglevel panic -accurate_seek -y -i '"$INFILE"' -strict -2 -ss "$1" -to "$2" 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. Это не является действительно необходимым и, вероятно, требует только загрузки процессорного времени.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .