Как разделить видео в формате mp4 с помощью ffmpeg каждый раз, когда громкость равна нулю? - PullRequest
0 голосов
/ 08 марта 2019

Мне нужно разделить видео на множество небольших видео.Я попробовал PySceneDetect и его 2 метода обнаружения сцены не соответствуют моим потребностям.

Идея состоит в том, чтобы вызывать обрезку / прерывание сцены каждый раз, когда громкость очень низкая, каждый раз, когда уровень звука ниже заданногопараметр.Я думаю, что общий уровень громкости RMS дБ - это то, что я имею в виду.

Цель состоит в том, чтобы разделить видео mp4 на множество коротких видео, каждое видео меньшего размера с короткими фразами диалогов.

Пока у меня естькоманда, чтобы получить общий уровень громкости звука RMS.

ffprobe -f lavfi -i amovie=01x01TheStrongestMan.mp4,astats=metadata=1:reset=1 -show_entries frame=pkt_pts_time:frame_tags=lavfi.astats.Overall.RMS_level,lavfi.astats.1.RMS_level,lavfi.astats.2.RMS_level -of csv=p=0

Как получить только минимальные значения для уровня RMS и соответствующего ему кадра или времени?

А затем как использовать ffmpegразделить видео на множество видео на каждый кадр, соответствующий минимальному среднеквадратическому значению?

Спасибо.

1 Ответ

3 голосов
/ 13 марта 2019

Используйте silencedetect аудиофильтр и подайте его выходные данные отладки в segment параметр формата вывода.

Вот готовый сценарий:

#!/bin/bash

IN=$1
OUT=$2

true ${SD_PARAMS:="-55dB:d=0.3"};
true ${MIN_FRAGMENT_DURATION:="20"};
export MIN_FRAGMENT_DURATION

if [ -z "$OUT" ]; then
    echo "Usage: split_by_silence.sh input_media.mp4 output_template_%03d.mkv"
    echo "Depends on FFmpeg, Bash, Awk, Perl 5. Not tested on Mac or Windows."
    echo ""
    echo "Environment variables (with their current values):"
    echo "    SD_PARAMS=$SD_PARAMS       Parameters for FFmpeg's silencedetect filter: noise tolerance and minimal silence duration"
    echo "    MIN_FRAGMENT_DURATION=$MIN_FRAGMENT_DURATION    Minimal fragment duration"
    exit 1
fi

echo "Determining split points..." >& 2

SPLITS=$(
    ffmpeg -nostats -v repeat+info -i "${IN}" -af silencedetect="${SD_PARAMS}" -vn -sn  -f s16le  -y /dev/null \
    |& grep '\[silencedetect.*silence_start:' \
    | awk '{print $5}' \
    | perl -ne '
        our $prev;
        INIT { $prev = 0.0; }
        chomp;
        if (($_ - $prev) >= $ENV{MIN_FRAGMENT_DURATION}) {
            print "$_,";
            $prev = $_;
        }
    ' \
    | sed 's!,$!!'
)


echo "Splitting points are $SPLITS"

ffmpeg -v warning -i "$IN" -c copy -map 0 -f segment -segment_times "$SPLITS" "$OUT"

Вы указываете входной файл, шаблон выходного файла, параметры обнаружения тишины и минимальный размер фрагмента, он записывает несколько файлов.

Параметры обнаружения Silence может должны быть настроены:

  • SD_PARAMS Переменная окружения содержит два параметра: уровень помехоустойчивости и минимальную продолжительность молчания. Значение по умолчанию -55dB:d=0.3.
  • Уменьшить -55dB до напр. -70dB если какие-то слабые немые звуки вызывают плевки, когда они не должны. Увеличьте его, например, до -40dB если он не разделяется на молчание из-за присутствия в нем шума, что делает его не совсем тихим.
  • d=0.3 - минимальная длительность паузы, которая должна рассматриваться как точка разделения. Увеличьте его, если только серьезное (например, целые 3 секунды) молчание следует рассматривать как реальное, достойное разделения молчание.
  • Другая переменная среды MIN_FRAGMENT_DURATION определяет количество событий молчания во времени, которые игнорируются после каждого разделения. Это устанавливает минимальную длительность фрагмента.

Сценарий завершится ошибкой, если не будет обнаружено никакого молчания.

На Github Gist существует измененная версия , но с ним была проблема для одного пользователя.

...