7 ответов:
Короткий ответ, нет.
Длинный ответ, да, но не без использования отдельной библиотеки для создания кадров с отрисованным кодом времени на них, с прозрачностью, заполняющей остальную часть кадра, а затем с помощью FFmpeg для наложения кадров на существующее видео. Я не знаю, как это сделать, но я уверен, что если вы творческий человек, вы можете понять это.
Edit: я работаю над этой проблемой, потому что это интересный вопрос/Проект Для меня. У меня есть продвиньтесь немного дальше в решении, написавсценарий Perl , который будет генерировать файл
.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Все еще работаем над тем, как расположить и наложить рендеринг субтитров на видео и перекодирование в том же формате. Я обновлю этот пост, как только узнаю больше.
Фильтр drawtext 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. Обратите внимание, что вы должны экранировать двоеточия в строке формата timecode, и вы должны указать скорость timecode (здесь 25fps). Вы также можете указать дополнительный текст-здесь это "TCR:"
Вы можете получить частоту кадров с помощью ffprobe и немного оболочки fu:
frame_rate=$(ffprobe -i "movie.mov" -show_streams 2>&1|grep fps|sed "s/.*, \([0-9.]*\) fps,.*/\1/")Так что вы можете легко подключить все это вместе в сценарии пакетной обработки, например
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Это добавило бы имя клипа и скользящий тайм-код в полупрозрачной коробке в нижнем центре кадра 1920х1080
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 заданную папку, содержащую .Мова, .MP4 и .Файлы MTS (с помощью команды
-filterон ищет файлы с *.М* в названии, которое вам придется изменить если бы ты это делал .AVI-файлы), и он немного более минимален, он просто использует libx264 с настройками по умолчанию в качестве выходного кодека и не указывает шрифт и т. д. Временной код в этом случае записывается в верхнем левом углу кадра.
Фильтр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 для возможных форматов):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
\\:используется для экранирования:, которое в противном случае получило бы значение разделителя опций.Другой пример: a команда для вставки даты и времени в черный прямоугольник, несколько пикселей от верхнего левого угла и "некоторые отступы" (на самом деле, два пробела и новые строки по краям):
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нарисует только второй текст. Вы можете комбинировать фильтры с запятой, как я показал выше.
В более поздних сборках вы можете использовать фильтр drawtext ("t" в его примерах, я полагаю, является временной меткой фрейма) для вставки текста. Он также работает для srtftime на "текущем" системном времени, а также.
Самое простое решение, которое я нашел, чтобы показать часы, когда файл был захвачен, а не его продолжительность и он работает /на основе этого поста, спасибо!/ 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: boxcolor=0x00000000@1" -f mp4 textts.mp4Так просто в тайм-коде-поставьте свое начальное время, тогда счет идет отлично! Пример для Windows
Вот мое решение, и я считаю, что оно правильное, потому что оно одновременно позволяет избежать необходимости вручную устанавливать скорость и позволяет форматировать выходные данные.
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 и опустил его прямо в рабочий каталог для простоты.
FFMPEG сможет выполнить большую часть работы, но она не будет полностью упакована. Используя FFMPEG, вы можете заставить его декодировать все кадры в последовательности и дать вам "метку времени презентации" (дополнительные метаданные, связанные с временем, могут быть доступны в некоторых форматах, но PTS-это то, что вы хотите искать, чтобы начать работу.) Затем вы сами должны нарисовать текст на декодированном фрейме самостоятельно. Я использую Qt для подобных вещей, используя QPainter на QImage с данными фрейма, но там возможно, есть какой-то другой API для рисования на изображении, которое вы находите более очевидным. Затем используйте API FFMPEG для создания сжатого видео, в котором есть только что нарисованные кадры. Это будет немного сложнее, если вы также хотите аудио. Моя собственная работа на самом деле не заботится об аудио, поэтому я не удосужился изучить звуковые аспекты API. В основном, когда вы делаете цикл чтения, получая пакеты из файла, некоторые из них будут аудио. Вместо того, чтобы выбрасывать их, как это делаю я, вам нужно будет сохранить их и запишите их в выходной файл, как вы их получили.
Я использовал только C API, а не C#, поэтому я не знаю, есть ли какие-то особые gotcha's, о которых стоит беспокоиться.
Comments