Скачивание audio c youtube и разбитие его на маленькие части

Задача вытащить звук из видео с youtube и разбить на файлы, продолжительностью несколько минут. Решаться данная задача будет с помощью ffmpeg (будет применяться установка в Docker контейнер для того чтобы использовать готовый скрипт разбивки файла).

Автоматизированное разбитие файла

  1. Скачать видео используя savefrom.net (в примерах ниже файл сохраняется с именем sample.avi)
  2. Установить в Docker контейнер ffmpeg (инструкция указана для Dockerfile)
RUN apt-get install -y ffmpeg
  1. Переместить файл с скаченным видео в папку, которая будет видна в контейнере
  2. Запустить контейнер
  3. Войти в контейнер
  4. Перейти в папку с видео
  5. Извлечь звук, выполнив:
ffmpeg -i sample.avi -q:a 0 -map a sample.mp3
  1. Сохранить скрипт в папку с видео (например в файл split):
#!/bin/bash
 
# Written by Alexis Bezverkhyy <alexis@grapsus.net> in 2011
# This is free and unencumbered software released into the public domain.
# For more information, please refer to <http://unlicense.org/>
 
function usage {
        echo "Usage : ffsplit.sh input.file chunk-duration [output-filename-format]"
        echo -e "\t - input file may be any kind of file reconginzed by ffmpeg"
        echo -e "\t - chunk duration must be in seconds"
        echo -e "\t - output filename format must be printf-like, for example myvideo-part-%04d.avi"
        echo -e "\t - if no output filename format is given, it will be computed\
 automatically from input filename"
}
 
IN_FILE="$1"
OUT_FILE_FORMAT="$3"
typeset -i CHUNK_LEN
CHUNK_LEN="$2"
 
DURATION_HMS=$(ffmpeg -i "$IN_FILE" 2>&amp;1 | grep Duration | cut -f 4 -d ' ')
DURATION_H=$(echo "$DURATION_HMS" | cut -d ':' -f 1)
DURATION_M=$(echo "$DURATION_HMS" | cut -d ':' -f 2)
DURATION_S=$(echo "$DURATION_HMS" | cut -d ':' -f 3 | cut -d '.' -f 1)
# fix error
DURATION_H=${DURATION_H#0}
DURATION_M=${DURATION_M#0}
DURATION_S=${DURATION_S#0}
let "DURATION = ( DURATION_H * 60 + DURATION_M ) * 60 + DURATION_S"
 
if [ "$DURATION" = '0' ] ; then
        echo "Invalid input video"
        usage
        exit 1
fi
 
if [ "$CHUNK_LEN" = "0" ] ; then
        echo "Invalid chunk size"
        usage
        exit 2
fi
 
if [ -z "$OUT_FILE_FORMAT" ] ; then
        FILE_EXT=$(echo "$IN_FILE" | sed 's/^.*\.\([a-zA-Z0-9]\+\)$/\1/')
        FILE_NAME=$(echo "$IN_FILE" | sed 's/^\(.*\)\.[a-zA-Z0-9]\+$/\1/')
        OUT_FILE_FORMAT="${FILE_NAME}-%03d.${FILE_EXT}"
        echo "Using default output file format : $OUT_FILE_FORMAT"
fi
 
N='1'
OFFSET='0'
let 'N_FILES = DURATION / CHUNK_LEN + 1'
 
while [ "$OFFSET" -lt "$DURATION" ] ; do
        OUT_FILE=$(printf "$OUT_FILE_FORMAT" "$N")
        echo "writing $OUT_FILE ($N/$N_FILES)..."
        ffmpeg -i "$IN_FILE" -vcodec copy -acodec copy -ss "$OFFSET" -t "$CHUNK_LEN" "$OUT_FILE"
        let "N = N + 1"
        let "OFFSET = OFFSET + CHUNK_LEN"
done

При копирование скрипта в Windows необходимо преобразовать символы переноса из CRLF (окончания строк в Windows) в LF (окончания строк в Unix). Сделать это можно в Nodepad++ (Правка -> Формат Конца Строк -> Преобразовать в UNIX-формат (LF)).

  1. Запустить скрипт в контейнере:
./split sample.mp3 300 sample_%04d.mp3

Эта позволит получить множество файлов вида sample_00XX.mp3, продолжительностью 300 секунд.

Ручное разбитие файла

В случае отсутствия возможности воспользоваться контейнером либо работе в Windows, можно воспользоваться ручным разбиением файлов:

ffmpeg -ss 0 -t 300 -i sample.mp3 sample_0001.mp3

В указанной команде параметры означают:

-ss 0 — Начать с 0 секунды
-t 300 — Продолжительность 30 секунд от места начала

Автоматизация извлечения звука и разбития на части

Для объединения действий по извлечению звука из видео и разбитию на части с сохранением результата в папке с именем входного файла предназначен скрипт audio.sh:

#!/bin/bash

if [ $# -ne 1 ]
then
  echo "Usage: '$0' audio source file"
  exit
fi

sourceFile=$1
targetName=`expr match "$1" '\(.*\)\.'`
audioFileName=${targetName}.mp3
echo ${sourceFile}
echo ${audioFileName}

ffmpeg -i $sourceFile -q:a 0 -map a $audioFileName

mkdir $targetName

./split ${audioFileName} 300 ${targetName}/$targetName%04d.mp3

rm ${audioFileName}

Пример использования:

./audio.sh video.mp4

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

Множественное разбитие файлов на составные части

Для последовательного разбития нескольких файлов можно воспользоваться скриптом (group.sh):

#!/bin/bash

./audio.sh file1.mp4
rm file1.mp4

./audio.sh file2.mp4
rm file2.mp4

Можно воспользоваться скриптом (split-all.sh), который автоматически найдет файлы *.mp4 и разобьет их на части (после разбиения исходные файлы удаляются):

#!/bin/bash

for file in `find -name "*.mp4"`
do
   ./audio.sh $file
   rm $file
done

Устранение ошибок при запуске bash скриптов

Если не удается запустить bash скрипты приведенные выше, рекомендуется ознакомиться с методом, описанным тут.