Объедините одно изображение + один аудиофайл, чтобы сделать одно видео, используя FFmpeg

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

Я хочу, чтобы FFmpeg взял одно изображение JPEG и аудиофайл в качестве входных данных и сгенерировал видеофайл той же длительности, что и аудиофайл (растягивая неподвижное изображение на всю длительность).

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

Какова правильная командная строка, которая сделала бы это?

Я старался:

ffmpeg -i image8.jpg -i sound11.amr -acodec copy test.avi

и перепробовал много комбинаций с и без -s 640x360, -loop_input, -shortest, -t xxx, -r 0.1 (искусственно низкая частота кадров в надежде, что видео будет длиннее) и -f image2

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

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

Кто-нибудь может предложить рабочую команду и объяснить обоснование этого?

15 ответов

Решение

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

ffmpeg -loop 1 -y -i image8.jpg -i sound11.amr -shortest -acodec copy -vcodec mjpeg result.avi

В более общем случае, где image.jpg а также audio.wav Вы можете использовать следующую команду, адаптированную из вики FFmpeg:

ffmpeg -loop 1 -i image.jpg -i audio.wav -c:v libx264 -tune stillimage -c:a aac -b:a 192k -pix_fmt yuv420p -shortest out.mp4

Это будет использовать libx264 кодировщик и обеспечит вам лучшее сжатие, чем кодек MJPEG, использованный выше. Аудио AAC, со встроенным ffmpeg Кодировщик AAC.

Еще проще:

ffmpeg -i ep1.png -i ep1.wav ep1.flv

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

Обновление: я заметил, что YouTube испытывает затруднения при обработке видео (застревает на 95%), я думаю, потому что есть только один кадр. Решение, которое я нашел, чтобы сделать YouTube счастливым: добавить больше кадров. Также я добавил-acodec copy сохранить качество звука. Тебе нужно -shortest или это зацикливается навсегда. (Он останавливается в конце самого короткого потока, который является аудио, потому что цикл изображения бесконечен.) Порядок ваших параметров очень важен для скорости, так как фильтры (и такие) обрабатываются в указанном вами порядке. Если вы измените порядок этих параметров, результаты резко отличаются.

ffmpeg -r 1 -loop 1 -i ep1.jpg -i ep1.wav -acodec copy -r 1 -shortest -vf scale=1280:720 ep1.flv

Также обратите внимание, что я установил частоту кадров дважды, это не случайно - первая частота кадров для входа, вторая для выхода. Если вы делаете это правильно, видео должно содержать только один кадр в секунду, что означает, что оно кодируется относительно быстро. Также я установил здесь разрешение 720p, что означает, что вы должны получать HD-аудио на YouTube:-)

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

ffmpeg -i still.png -i narrate.wav -acodec libvo_aacenc -vcodec libx264 final.flv

pause

Единственные атрибуты, которые вы должны указать, это input filenames, output codecs и output filename (который включает в себя ipso output container)

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

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

pause Команда в конце командного файла сохраняет CLI открытым - лучший способ отладки вашей командной строки - чтение сообщений об ошибках, которые она генерирует. Они чрезвычайно специфичны - и лучшая документация, которую имеет FFmpeg - но тяжелая работа разработчиков будет потрачена впустую, если вы позволите закрыть окно, прежде чем сможете их прочитать.

Командная оболочка имеет переключатель cmd /k в нем есть открытое окно, в котором вы можете выполнить те же инструкции из вашего пакетного сценария в командной строке.

FFmpeg и avconv заставят вас использовать -c:a за -acodec а также -c:v за -vcodec в конце концов, но старые инструкции хорошо работают в сборках, которые я использую.

Nota Bene: Каждый коммит имеет свои особенности. Если ваша командная строка дает сбой без видимой причины, часто бывает полезно попробовать другую сборку или перейти к libav, где последние два года самые активные разработчики FFmpeg работали. Их инструмент транскодирования был переименован в avconv, но ваши командные файлы должны работать с любым из них.

Версия, которая работала для меня:

 ffmpeg -loop 1 -y -i pic.jpg -i sound.amr -shortest video.mp4

Оформить заказ -shortest должен быть перед выходным файлом, если нет, я получаю следующую ошибку:

Самый короткий параметр (завершить кодирование при самом коротком вводе) не может быть применен к входному файлу pic.jpg - вы пытаетесь применить параметр ввода к выходному файлу или наоборот. Переместите эту опцию перед файлом, которому она принадлежит. Ошибка анализа параметров входного файла pic.jpg.

Из справочной страницы ffmpeg:

ffmpeg [[infile options][-i infile]]... {[outfile options] outfile}...

Как вы обнаружили, варианты infile должны предшествовать infile, к которому они применяются.

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

Вот полное объяснение:

ffmpeg -i image.jpg -i audio.mp3 -c:v libx264 -tune stillimage -c:a copy out.mp4

Я не пользовалась -loop 1 или -shortest, -loop 1 резко замедляет кодирование и создает больший файл. -shortest не должен использоваться без -loop 1 с тех пор видео будет длиться один кадр. Однако YouTube не любит видео с одним кадром (см. Ответ PJ Brunet), поэтому следует использовать оба варианта.

Это сработало для меня

ffmpeg -loop 1 -shortest -y -i image.jpg -i audio.mp3 -acodec copy -vcodec libx264 video.avi

Я нашел vcodec libx264 создал гораздо меньшие файлы, чем mpjeg (10 МБ, а не 100 МБ).

Клонирован из PJ Brunetответ:

ffmpeg -r 1 -loop 1 -y -i 1.jpg -i 1.m4a -c:a copy -r 1 -vcodec libx264 -shortest 1.avi

В результате получается наименьший размер (18 МБ) и самое быстрое время кодирования (для файла m4a размером 17 МБ потребовалось всего 2 секунды)

Я пытался сделать как @matteo, но без звука, и решение @Colonel Panic работало лучше всего:

ffmpeg -loop 1 -shortest -y -i still.png -vcodec libx264 -t 10 video.avi

Мне нужно было добавить аргумент продолжительности в секундах (-t 10).

Я использовал комбинацию из нескольких команд, упомянутых в этом посте, в том числе -pix_fmt yuv420p чтобы убедиться, что он работает на Quicktime (Mac).

ffmpeg -loop 1 -y -i image.jpg -i music.mp3 -shortest -pix_fmt yuv420p output.mp4

Для меня это отлично работает на MacOS.

Если кто-то хочет конвертировать их, попробуйте это.

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

Этот ответ Объединение одного изображения + одного аудиофайла для создания одного видео с использованием FFmpeg мне очень помогло.

 @echo off
 set "sourcedir=C:\Users\CodeHard\Desktop\BOX\Newfolder"  
 set "outputdir=C:\Users\CodeHard\Desktop\BOX\Converted" 

 PUSHD "%sourcedir%"

 for %%F in (*.mp3) DO ffmpeg -r 1 -loop 1 -i abc.jpeg -i "%%F" -acodec copy -r 1 -shortest -vf scale=1280:720 "%outputdir%\%%F.avi"  

 POPD

ffmpeg -loop 1 -i img.jpg -i audio.wav -c:v libx264 -c:a aac -strict experimental -b:a 192k -shortest out.mp4

Докер

У меня аналогичная проблема с преобразованием .wma (аудиофайлов) в .mp4 и загрузкой результата на YouTube - я оставлю работающее решение для докеров для дальнейшего чтения.

      version: '3.7'

services:
    convert:
        image: jrottenberg/ffmpeg
        volumes:
            - ./mp3:/data
        
        # for WMV
        command: ' -loop 1 -framerate 2 -i "/data/image.jpeg" -i "/data/myAudio.WMA" -c:v libx264 -preset medium -tune stillimage -crf 18 -c:a aac -b:a 128k -shortest -pix_fmt yuv420p "/data/myVideoForYT.mp4" -stats'

        # for .mp3
        #command: ' -loop 1 -framerate 2 -i "/data/image.jpeg" -i "/data/myAudio.mp3" -c:v libx264 -preset medium -tune stillimage -crf 18 -c:a copy -shortest -pix_fmt yuv420p "/data/myVideoForYT.mp4" -stats'

Сохраните код ниже внутриdocker-composer.ymlфайл, я предполагаю, чтоmp3каталог (с файлом myAudio.wma) будет находиться в том же каталоге. И запустите егоdocker compose run convert(вы должны видеть прогресс/продолжительность обработки)

Поскольку на протяжении всего видео отображается только одно изображение, мы можем уменьшить частоту кадров, чтобы она соответствовала продолжительности звука. Затем мы просто объединяем изображение и звук в контейнере MKV.

  1. Найдите длину аудиофайла
      ffprobe -i <audio input> -show_entries format=duration -v quiet -of csv="p=0"
  1. Кодируйте видео
      ffmpeg -framerate 1/<length> -i <image input> -i <audio input> -vcodec copy -acodec copy output.mkv

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

Попробуйте эту команду. Это работает для меня.

-y -i /storage/emulated/0/images.jpg -i /storage/emulated/0/audio.wav -acodec aac -vcodec mpeg4 -s 480*320 -f mp4 -r 2 /storage/emulated/0/output.mp4"
Другие вопросы по тегам