Подтвердить что ты не робот

Может ffmpeg записать во временном коде?

У меня есть необходимость записать во временном коде видео, и мне интересно, возможно ли это для ffmpeg?

4b9b3361

Ответ 1

Короткий ответ, нет.

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

Изменить: Я работаю над этой проблемой, потому что это интересный вопрос/проект для меня. Я пришел немного дальше в решении, написав Perl script, который сгенерирует файл .srt с временным кодом, встроенным в он для любого данного видеофайла, с которого FFmpeg настроен так, чтобы читать метаданные. Он использует библиотеку Video::FFmpeg для чтения продолжительности и сохраняет файл субтитров как ${video}.srt. Это сделает так, что он автоматически отобразится в Mplayer, если вы введете следующие строки в ~/.mplayer/config:

# select subtitle files automatically in the current directory, all files
# matching the basename of the current playing file
sub-fuzziness=1

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

Ответ 2

Фильтр рисования FFMPEG работает для меня, вы указываете начальный тайм-код и его формат:

-vf drawtext="fontsize=15:fontfile=/Library/Fonts/DroidSansMono.ttf:\
timecode='00\:00\:00\:00':rate=25:text='TCR\:':fontsize=72:fontcolor='white':\
boxcolor=0x000000AA:box=1:x=860-text_w/2:y=960"

вам нужно указать формат временного кода в форме hh: mm: ss [:;,] ff. Обратите внимание, что вам нужно избегать двоеточий в строке формата временного кода, и вам нужно указать скорость временного кода (здесь 25 кадров в секунду). Вы также можете указать дополнительный текст - здесь он "TCR:"

Вы можете получить частоту кадров с ffprobe и немного оболочки fu:

frame_rate=$(ffprobe -i "movie.mov" -show_streams 2>&1|grep fps|sed "s/.*, \([0-9.]*\) fps,.*/\1/")

Итак, вы можете легко подключить все вместе в пакетной обработке script, например

for i in *.mov
frame_rate=$(ffprobe -i "$i" -show_streams 2>&1|grep fps|sed "s/.*, \([0-9.]*\) fps,.*/\1/")
clipname=${(basename "$i")/\.*/}
ffmpeg -i "$i" -vcodec whatever -acodec whatever \
-vf drawtext="fontsize=15:fontfile=/Library/Fonts/DroidSansMono.ttf:\
timecode='00\:00\:00\:00':rate=$frame_rate:text='$clipname' TCR:':\
fontsize=72:fontcolor='white':boxcolor=0x000000AA:\
box=1:x=860-text_w/2:y=960" "${i/.mov/_tc.mov}"
done

Это добавит имя клипа и катит timecode в полупрозрачном поле в нижнем центре кадра 1920x1080

Edit Поскольку я пришел на темную сторону, теперь я делаю это в среде Windows Powershell, и это то, что я использую:

ls -R -File -filter *.M*|%{
ffmpeg -n -i $_.fullname -vf drawtext="fontsize=72:x=12:y=12:`
timecode='00\:00\:00\:00':rate=25:fontcolor='white':`
boxcolor=0x000000AA:box=1" `
("c:\path\to\destination\{0}" -F ($_.name -replace 'M[OPT][V4S]', 'mp4'))}

Это создает mp4s для папки, содержащей файлы .MOV,.MP4 и .MTS(с помощью команды -filter она ищет файлы с *.M * в имени, которые вам нужно будет изменить, если вы делаете. AVI), и он немного более минимален, он просто использует libx264 с настройками по умолчанию в качестве выходного кодека и не указывает шрифт и т.д. Временной код в этом случае сжигается в левом верхнем углу кадра.

Ответ 3

Фильтр drawtext, упомянутый в @stib, является ключом для вставки времени. Однако использование опции timecode не соответствует времени настенных часов. Если вы ошиблись в параметре r (timecode_rate), то ваше время не будет соответствовать вашему времени воспроизведения.

Существуют и другие варианты, например опция text='%{prt}' позволяет отображать прошедшее время с точностью до микросекунды. Команда:

ffmpeg -i video.mp4 -vf "drawtext=text='%{prt}'" output.mp4

Чтобы получить часы вместо этого, мне пришлось использовать устаревший вариант strftime. Это имеет недокументированную опцию basetime, которая может использоваться для установки времени начала в микросекундах. Пример, когда я установил время запуска до 12:00 PM 1 декабря 2013 года (часть $(...) - это расширение оболочки, выполняемое оболочкой) и отображает только время (см. strftime manual для возможных форматов):

ffmpeg -i video.mp4 -vf "drawtext=expansion=strftime: \
    basetime=$(date +%s -d'2013-12-01 12:00:00')000000: \
    text='%H\\:%S\\:%S'" output.mp4

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

Еще один пример: команда вставить дату + время в черный ящик, на несколько пикселей в верхнем левом углу и "некоторое заполнение" (на самом деле, два пробела и новые строки на краях):

newline=$'\r'
ffmpeg -i video.mp4 -vf "drawtext=x=8:y=8:box=1:fontcolor=white:boxcolor=black: \
    expansion=strftime:basetime=$(date +%s -d'2013-12-01 12:00:00')000000: \
    text='$newline %Y-%m-%d %H\\:%M\\:%S $newline'" output.mp4

Еще один пример, чтобы получить микросекунды ниже часов:

newline=$'\r'
ffmpeg -i video.mp4 -vf "drawtext=expansion=strftime: \
    basetime=$(date +%s -d'2013-12-01 12:00:00')000000: \
    text='$newline %H\\:%M\\:%S $newline':fontcolor=white:box=1:boxcolor=black, \
    drawtext=text='$newline %{pts} $newline': \
    y=2*th/3:box=1:fontcolor=white:boxcolor=black:" output.mp4

Это использует тот факт, что текст на самом деле состоит из трех строк и что оба текста имеют новую строку (возврат каретки, ^M), добавленную и добавленную. (Без этой новой строки пространство становится лишенным)

Другие советы:

  • -vf и -filter:v равны.
  • Вы не можете указывать фильтры несколько раз, например. -vf drawtext=text=1 -vf drawtext=text=2 будет выводить только второй текст. Вы можете комбинировать фильтры с запятой, как я показал выше.

Ответ 4

в более поздних сборках вы можете использовать drawtext фильтр ( "t" в своих примерах есть, я считаю, временная метка кадра) для вставки текста. Он также работает для srtftime и в "текущем" системном времени.

Ответ 5

Самое простое решение, которое я обнаружил, чтобы показать часы, когда файл был захвачен, а не его продолжительность, и он работает/основан на этом сообщении, спасибо! /is

D:\Temp\2>ffmpeg.exe -i test.avi -vf "drawtext=fontfile=C\\:/Windows/Fonts/arial.ttf:timecode='00\:20\:10\:00':rate=25:text='TCR\:':fontsize=46:fontcolor=white:x=500:y=50: box=1: [email protected]"  -f mp4 textts.mp4

Так просто в timecode - поставьте свое начальное время, тогда подсчет идет хорошо! Пример для Windows

Ответ 6

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

ffmpeg -i test.mp4 -vf \
    "drawtext=fontfile=arialbd.ttf:text='%{pts\:gmtime\:0\:%H\\\:%M\\\:%S}'" test.avi

Это создает штамп в формате HH: MM: SS; вы можете изменить его на все, что захотите, используя strftime.

Может показаться, что это будет помечено в метку времени с gmtime, но это не то, что происходит. Он фактически передает текущее время видео, в секундах, в gmtime, производя дату, которая составляет 1/1/1970, и время, которое, однако, много секунд после полуночи. Таким образом, вы просто отбрасываете часть даты и используете временную часть.

Обратите внимание на тройные экранированные двоеточия внутри функции pts, которые вам нужно будет сделать, если вы введете их, как я сделал выше. Также вы можете увидеть, что я скопировал свой файл шрифтов для Arial Bold и бросил его прямо в рабочий каталог для простоты.

Ответ 7

FFMPEG сможет выполнять большую часть работы, но не будет полностью упакован. Используя FFMPEG, вы можете последовательно декодировать все кадры и предоставить вам "Временной штамп времени" (дополнительные метаданные времени могут быть доступны в некоторых форматах, но PTS - это то, что вы хотите найти для начала.) Затем вы сами можете нарисовать текст на декодированном фрейме самостоятельно. Я использую Qt для подобных вещей, используя QPainter в QImage с данными фрейма, но может быть и другой API, чтобы нарисовать изображение, которое вы считаете более очевидным. Затем используйте API FFMPEG для создания сжатого видео, в котором есть ваши недавно нарисованные кадры. Это будет немного сложнее, если вы также хотите аудио. Моя собственная работа на самом деле не волнует звук, поэтому я не потрудился изучить аудио-аспекты API. В основном, поскольку вы делаете свой цикл чтения, получая пакеты из файла, некоторые из них будут аудио. Вместо того, чтобы отбрасывать их, как я, вам нужно сохранить их и записать их в выходной файл по мере их получения.

Я использовал API C, а не С#, поэтому я не знаю, есть ли какие-то особые проблемы, о которых вы беспокоитесь.