Превратите аудио в общедоступное видео с помощью Python и FFmpeg

Python
Превратите аудио в общедоступное видео с помощью Python и FFmpeg

В этом уроке мы узнаем, как использовать Python иFFmpegСоздайте приложение, которое позволит нам превращать голосовые записи в крутые видеоролики, которыми можно легко поделиться в социальных сетях.

К концу этого урока мы превратим голосовую запись в видео, похожее на показанное ниже.

Project demo

Требования к учебнику

Чтобы следовать этому руководству, вам понадобятся следующие компоненты.

  • Одна или несколько голосовых записей, которые вы хотите преобразовать в видео. Программируемые голосовые записи, хранящиеся в вашей учетной записи Twilio, очень полезны для этого руководства.
  • установленPython3,6+.
  • УстановитьFFmpegВерсия 4.3.1 или выше.

Создать структуру проекта

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

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

mkdir twilio-turn-recording-to-video
cd twilio-turn-recording-to-video

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

mkdir images
mkdir fonts
mkdir videos
mkdir recordings

imagesВ каталоге мы будем хранить фоновое изображение для видео. скачатьэто изображение, и сохраните его вimagesкаталог с именемbg.png. Это изображение изначально было взято изFreepik.comскачать.

существуетfontsкаталог, где мы будем хранить файлы шрифтов, используемые для написания текста в нашем видео. скачатьэтот шрифт, и сохраните его вfontsкаталог с именемLeagueGothic-CondensedRegular.otf. Этот шрифт изначально былfontsquirrel.comскачать.

videosКаталог будет содержать видео и анимацию, которые будут добавлены поверх фонового изображения. скачатьэтоВращающаяся пластинка с логотипом Twilio посерединевидео, и сохраните его вvideosкаталог с именемspinningRecord.mp4. Исходные изображения, используемые в этом видео, взяты изflaticon.comскачать.

recordingsВ каталоге мы будем хранить голосовые записи, которые будут преобразованы в видео. Добавьте в этот каталог одну или несколько собственных голосовых записей.

Теперь, когда мы создали все необходимые каталоги, откройте свой любимый редактор кода и создайте файл в каталоге верхнего уровня вашего проекта с именемmain.pyдокумент. Этот файл будет содержать код, отвечающий за превращение нашей записи в видео.

Если вы не хотите повторять каждый шаг руководства, вы можетеэто здесьПолучите полный исходный код проекта.

Превратите аудиофайл в видео

В этом разделе мы добавим код, который позволит нам превратить запись в видео, отображающее звуковые волны записи.

мы будем использоватьFFmpeg, который генерирует видео из аудиофайла. Поэтому для вызова FFmpeg и связанных с ним программ из Python мы будем использоватьsubprocessмодуль.

выполнить команду

существуетmain.pyДобавьте в файл следующий код.

import subprocess


def run_command(command):
    p = subprocess.run(
        command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
    )
    print('Done!!!')
    print('stdout:\n{}'.format(p.stdout.decode()))

    return p.stdout.decode().strip()

В приведенном выше блоке кода мы импортировалиsubprocessмодуль и создалrun_command()функция. Как следует из названия, эта функция отвечает за выполнение команды с переданными аргументами. Когда команда завершается, мы печатаем вывод и возвращаем его вызывающей стороне.

Получить продолжительность записи

существуетrun_command()Добавьте следующий код ниже функции.

def get_rec_duration(rec_name):
    rec_path = "./recordings/{}".format(rec_name)

    command = "ffprobe -i {rec_path} -show_entries format=duration -v quiet \
    -of csv=\"p=0\"".format(rec_path=rec_path)

    rec_duration = run_command(command)
    print("rec duration", rec_duration)

    return rec_duration

Здесь мы создаемget_rec_duration()Функция. Эта функция отвечает за получение продолжительности записи. Функция получает имя записи (rec_name) в качестве параметра с префиксом имени каталога записи, который хранится вrec_pathв локальных переменных.

ffprobeПрограмма является частью FFmpeg и используется для создания командной строки для получения продолжительности записи. Вызываем этой командойrun_command()функцию и сохранить возвращенное значение вrec_duration.

Наконец, мы печатаем, затем возвращаем полученное время записи.

Продолжительность записи требуется, чтобы указать, что продолжительность видео, которое будет создано, одинакова.

Конвертировать аудио в видео

существуетget_rec_duration()Добавьте следующий код ниже функции.

def turn_audio_to_video(rec_name, rec_duration):
    rec_path = "./recordings/{}".format(rec_name)
    bg_image_path = "./images/bg.png"
    video_name = "video_with_sound_waves.mp4"

    command = 'ffmpeg -y -i {rec_path} -loop 1 -i {bg_image_path} -t {rec_duration} \
    -filter_complex "[0:a]showwaves=s=1280x150:mode=cline:colors=00e5ff[fg];  \
    drawbox=x=0:y=285:w=1280:h=150:color=black@0.8:t=fill[bg]; \
    [bg][fg]overlay=format=auto:x=(W-w)/2:y=(H-h)/2 " \
    -map 0:a -c:v libx264 -preset fast -crf 18 -c:a aac \
    -shortest ./videos/{video_name}'.format(
        rec_path=rec_path,
        bg_image_path=bg_image_path,
        rec_duration=rec_duration,
        video_name=video_name,
    )

    print(video_name)
    run_command(command)
    return video_name

turn_audio_to_video()Функция превратит запись в видео, показывающее звуковые волны записи. Функция начинается с имени записи (rec_name) и время записи (rec_duration) в качестве параметра.

Команда FFmpeg для создания видео из аудио использует путь записи (rec_path), путь к фоновому изображению (bg_image_path) и имя выходного файла видео (video_name).

Давайте подробнее рассмотрим команды FFmpeg.

ffmpeg -y -i {rec_path} -loop 1 -i {bg_image_path} -t {rec_duration} \
-filter_complex \"[0:a]showwaves=s=1280x150:mode=cline:colors=00e5ff[fg];  \
drawbox=x=0:y=285:w=1280:h=150:color=black@0.8:t=fill[bg]; \
[bg][fg]overlay=format=auto:x=(W-w)/2:y=(H-h)/2 \" \
-map 0:a -c:v libx264 -preset fast -crf 18 -c:a aac -shortest ./videos/{video_name}

Должен[-y](https://ffmpeg.org/ffmpeg-all.html#Main-options)Скажите ffmpeg перезаписать выходной файл, если он существует на диске.

Должен[-i](https://ffmpeg.org/ffmpeg-all.html#Main-options)Опции указывают, что вводить. В этом примере у нас есть 2 входных файла, файл записи,rec_path, изображение, которое мы используем, имеет фон, который хранится вbg_image_path.

Должен[-loop](https://ffmpeg.org/ffmpeg-all.html#loop)Возможность создания видео путем повторения (зацикливания) входного файла. Здесь мы зацикливаемсяbg_image_pathизображение введено в . Значение по умолчанию0(не зацикливание), поэтому мы устанавливаем его на1(цикл), чтобы повторить это изображение во всех кадрах видео.

Должен[-t](https://ffmpeg.org/ffmpeg-all.html#Main-options)option указывает продолжительность в секундах, или используйте"hh:mm:ss[.xxx]"грамматика. Здесь мы используем продолжительность записи (rec_duration) значение, чтобы установить продолжительность нашего выходного видео.

[-filter_complex](https://ffmpeg.org/ffmpeg.html#filter_005fcomplex_005foption)Фильтр: позволяет нам определить сложный граф фильтра, фильтр с любым количеством входов и/или выходов. Это сложный вариант и требует некоторых параметров, обсуждаемых ниже.

Во-первых, мы используемshowwavesфильтр для преобразования голосовых записей, цитируемых как[0:a], вывод как видео.sПараметр используется для указания размеров выходного видео, мы устанавливаем его на 1280x150.modeПараметр определяет, как отрисовывается звуковая волна. Доступные значения .point,line,p2p, иcline.colorsПараметр определяет цвет сигнала. Рисунок осциллограммы указывается в виде метки[fg].

Мы используемdrawboxФильтр рисует цветную рамку на нашем фоновом изображении, чтобы выделить сигнал.x and yПараметр задает координаты левого верхнего угла прямоугольника, аw and hзатем установите его ширину и высоту.colorПараметр настраивает цвет поля какblack, с непрозрачностью 80%.tПараметр задает толщину границы блока. Установив это значение вfill, мы создаем сплошную коробку.

Чтобы завершить определение этого фильтра, мы используемoverlay, поместите график осциллограммы поверх черной рамки.overlayКонфигурация фильтра такова:format, который автоматически устанавливает формат пикселей;x and y, который указывает координаты наложения в видеокадре. Мы используем некоторую математику, чтобы указатьxиyДолжен быть в центре нашего видео.

Должен[-map](https://ffmpeg.org/ffmpeg.html#Stream-selection)Параметры используются для выбора входных потоков, которые должны быть включены или исключены из вывода. Мы решили объединить все потоки данных из наших записей в наше выходное видео.

Должен[-c:v](https://ffmpeg.org/ffmpeg.html#Stream-specifiers-1)Параметры используются для кодирования видеопотока и использования определенного кодека. Мы говорим FFmpeg использоватьlibx264Кодер.

Должен[-preset](https://trac.ffmpeg.org/wiki/Encode/H.264)Параметры Можно выбрать ряд параметров для обеспечения определенной скорости кодирования и коэффициента сжатия. То, что мы используем здесь, этоfastпараметры, но не стесняйтесь изменить предустановку на более медленную (лучшее качество) или более быструю (более низкое качество), если хотите.

Должен[-crf](https://trac.ffmpeg.org/wiki/Encode/H.264)Опции представляют коэффициенты постоянной скорости. Управление скоростью определяет, сколько битов будет использовать каждый кадр. Это определит размер файла и качество выходного видео. Для визуального качества без потерь рекомендуется значение 18.

Должен-[c:a](https://ffmpeg.org/ffmpeg.html#Stream-specifiers-1)Опции используются для кодирования аудиопотока с помощью определенного кодека. мы используемAACКодеки кодируют звук.

Должен[-shortest](https://ffmpeg.org/ffmpeg.html#toc-Advanced-options)Опция сообщает FFmpeg о прекращении записи вывода, когда заканчивается самый короткий входной поток.

в конце команды./videos/{video_name}Опции указывают путь к нашему выходному файлу.

Если вам интересно, вот что делают все рассмотренные выше режимы формы волны FFmpeg и как они выглядят.

PointНарисуйте точку для каждого образца.

Point waveform mode

Line, проведите вертикальную линию для каждого образца.

Line waveform mode

P2pНарисуйте точку для каждого образца и линию между ними.

P2p waveform mode

ClineНарисуйте центрированную вертикальную линию для каждого образца. Это то, что мы используем в этом уроке.

Cline waveform mode

существуетturn_audio_to_video()Добавьте следующий код ниже функции.

def main():
    rec_name = "rec_1.mp3"
    rec_duration = get_rec_duration(rec_name)
    turn_audio_to_video(rec_name,rec_duration)


main()

В этом недавно введенном коде у нас есть файл с именемmain()Функция. В нем мы сохраняем имя записи в файле с именемrec_nameв переменной. Вы должны обновить эту строку, включив в нее имя вашего собственного файла записи.

После этого звонимget_rec_duration()функция, чтобы получить время записи.

Затем мы звоним с названием записи и продолжительностьюturn_audio_to_videoфункцию и сохранить возвращенное значение вvideo_with_sound_wavesв переменной.

Наконец, мы вызываемmain()функция для запуска всего процесса. Не забудьте заменить на имя записи, которую вы хотите обработатьrec_nameзначение переменной.

Вернувшись в терминал, выполните следующую команду, чтобы сгенерировать видео.

python main.py

существуетvideosНайдите каталог с именемvideo_with_sound_waves.mp4файл, откройте его, и вы должны увидеть что-то похожее на следующее.

Waveform rendering

Добавить видео поверх фона

В этом разделе мы добавим видео с вращающимся диском в нижний левый угол полученного видео. Видео, которое мы хотим добавить, хранится вvideosкаталог с именемspinningRecord.mp4в файле.

Spinning record animation

Вернувшись в редактор кода, откройтеmain.pyфайл, и вturn_audio_to_video()Добавьте следующий код ниже функции.

def add_spinning_record(video_name, rec_duration):
    video_path = "./videos/{}".format(video_name)
    spinning_record_video_path = "./videos/spinningRecord.mp4"
    new_video_name = "video_with_spinning_record.mp4"

    command = 'ffmpeg -y -i {video_path} -stream_loop -1 -i {spinning_record_video_path} \
    -t {rec_duration} -filter_complex "[1:v]scale=w=200:h=200[fg]; \
    [0:v] scale=w=1280:h=720[bg], [bg][fg]overlay=x=25:y=(H-225)" \
    -c:v libx264 -preset fast -crf 18 -c:a copy \
    ./videos/{new_video_name}'.format(
        video_path=video_path,
        spinning_record_video_path=spinning_record_video_path,
        rec_duration=rec_duration,
        new_video_name=new_video_name,
    )

    print(new_video_name)
    run_command(command)
    return new_video_name

Здесь мы создалиadd_spinning_record()Функция. Эта функция будет отвечать за добавление на видео показ звуковых волнspinningRecord.mp4видео. Его аргументом является имя ранее сгенерированного видео (video_name) и время записи (rec_duration).

Эта функция также запускает FFmpeg. Ниже приведены подробности команды.

$ ffmpeg -y -i {video_path} -stream_loop -1 -i {spinning_record_video_path} \
-t {rec_duration} -filter_complex \"[1:v]scale=w=200:h=200[fg]; \
 [0:v] scale=w=1280:h=720[bg], [bg][fg]overlay=x=25:y=(H-225)\" \
-c:v libx264 -preset fast -crf 18 -c:a copy ./videos/{new_video_name}

Приведенная выше команда имеет следующие параметры.

-y,-t,-c:v,-preset, и-crfПараметры такие же, как у команды FFmpeg для создания звуковых волн.

-iЭта опция также использовалась ранее, но в этом случае у нас есть 2 видео в качестве входных файлов, видеофайл, созданный на предыдущем шаге, и повернутый видеофайл записи.

Должен[-stream_loop](https://ffmpeg.org/ffmpeg.html#Stream-copy)Параметры позволяют нам установить количество циклов входного потока. Значение 0 означает отключение цикла, а -1 означает бесконечный цикл. Мы устанавливаем крутящееся записанное видео на бесконечный цикл. Это позволит FFmpeg бесконечно кодировать выходное видео, но поскольку мы также указали продолжительность выходного видео, когда видео достигнет этой продолжительности, FFmpeg прекратит кодирование.

-filter_complexПАРАМЕТРЫ: Та же функция, что и раньше, но здесь у нас есть 2 видео в качестве входных файлов, созданных в предыдущем разделе.[0:v], и поверните записанное видео[1:v].

Этот фильтр впервые используется[scale](https://ffmpeg.org/ffmpeg-filters.html#scale)изменить размер повернутого видеозаписи до размеров 200x200 и назначить ему[fg]Тег. Затем снова используемscaleфильтр, установите размер видео, созданного в предыдущем разделе, на 1280x720 и добавьте[bg]Тег. Наконец, мы используем[overlay](https://ffmpeg.org/ffmpeg-filters.html#overlay)Фильтр помещает повернутое записанное видео поверх видео, созданного в предыдущем разделе, с координатамиx=25y=H-225(H означает высоту видео).

-c:aПараметры также описаны в предыдущем разделе, но в этом примере мы используем специальные значения.copy, который указывает ffmpeg копировать аудиопоток из исходного видео без его повторного кодирования.

Последняя часть команды,./videos/{new_video_name}, чтобы установить путь к нашему выходному файлу.

Замените следующимmain()код внутри функции, которая добавляет кadd_spinning_record()вызов функции.

def main():
    rec_name = "rec_1.mp3"
    rec_duration = get_rec_duration(rec_name)
    video_with_sound_waves = turn_audio_to_video(rec_name, rec_duration)
    add_spinning_record(video_with_sound_waves, rec_duration)

Запустите следующую команду в своем терминале, чтобы создать видео.

python main.py

существуетvideosНайдите каталог с именемvideo_with_spinning_record.mp4файл, откройте его, и вы должны увидеть что-то похожее на следующее.

Waveform rendering with spinning record

Добавить текст к видео

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

Вернувшись в редактор кода, откройтеmain.pyфайл, и вadd_spinning_recordДобавьте следующий код ниже функции.

def add_text_to_video(video_name):
    video_path = "./videos/{}".format(video_name)
    new_video_name = "video_with_text.mp4"
    font_path = "./fonts/LeagueGothic-CondensedRegular.otf"

    command = "ffmpeg -y -i {video_path} -vf \"drawtext=fontfile={font_path}:  \
    text='Turning your Twilio voice recordings into videos':fontcolor=black: \
    fontsize=90:box=1:boxcolor=white@0.5 \
    :boxborderw=5:x=((W/2)-(tw/2)):y=100\" \
    -c:a copy ./videos/{new_video_name}".format(
        video_path=video_path,
        font_path=font_path,
        new_video_name=new_video_name
    )

    print(new_video_name)
    run_command(command)
    return new_video_name

В этой функции мы создаем файл с именемadd_text_to_video()функция, которая вызывает новую команду FFmpeg для рисования текста. Давайте подробнее рассмотрим эту команду FFmpeg.

ffmpeg -y -i {video_path} -vf \"drawtext=fontfile={font_path}:  \
text='Turning your Twilio voice recordings into videos':fontcolor=black: \
fontsize=90:box=1:boxcolor=white@0.5:boxborderw=5:x=((W/2)-(tw/2)):y=100\" \
-c:a copy ./videos/{new_video_name}

-y-c:aОпции используются точно так же, как и раньше.

-ioptions, определяет вход, и теперь есть только один входной файл, видеофайл, созданный в предыдущем разделе.

Должен-[vf](https://ffmpeg.org/ffmpeg.html#Stream-copy)параметры позволяют нам создать простойfiltergraphи используйте его для фильтрации потока. Здесь мы используем это[drawtext](https://ffmpeg.org/ffmpeg-filters.html#drawtext-1)Фильтр рисует текст поверх видео с некоторыми параметрами:fontfileфайл шрифта, используемый для рисования текста,textопределяет текст, который будет нарисован (который можно свободно изменить по своему вкусу),fontcolorустановить цвет текста на черный,fontsizeустановить размер текста,boxвключить рамку вокруг текста,boxcolorУстановите цвет этого поля наwhite, непрозрачность 50%,boxborderwустановить ширину ограничивающей рамки,x and yУстанавливает положение текста в видео для печати. Мы рисуем текст посередине с небольшой математикой.

Последний./videos/{new_video_name}Опция задает выходной файл, как и в предыдущих командах FFmpeg.

Замените на версию нижеmain()Код в функции, которая добавляет шаг заголовка.

def main():
    rec_name = "rec_1.mp3"
    rec_duration = get_rec_duration(rec_name)
    video_with_sound_waves = turn_audio_to_video(rec_name, rec_duration)
    video_with_spinning_record = add_spinning_record(video_with_sound_waves, rec_duration)
    video_with_text = add_text_to_video(video_with_spinning_record)

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

python main.py

существуетvideosНайдите каталог с именемvideo_with_text.mp4файл, откройте его, и вы должны увидеть что-то похожее на следующее.

Waveform rendering with spinning record and title

Эпилог

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