У меня есть необходимость записать во временном коде видео, и мне интересно, возможно ли это для ffmpeg?
Может ffmpeg записать во временном коде?
Ответ 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, а не С#, поэтому я не знаю, есть ли какие-то особые проблемы, о которых вы беспокоитесь.