FFmpeg рисует текст на нескольких строках

У меня есть код:

import subprocess , os

ffmpeg = "C:\\ffmpeg_10_6_11.exe"
inVid = "C:\\test_in.avi"
outVid = "C:\\test_out.avi"

if os.path.exists( outVid ):
os.remove( outVid )
proc = subprocess.Popen(ffmpeg + " -i " + inVid + ''' -vf drawtext=fontfile=/Windows/Fonts/arial.ttf:text="onLine1 onLine2 onLine3":fontcolor=white:fontsize=20 -y ''' + outVid , shell=True, stderr=subprocess.PIPE)
proc.wait()
print proc.stderr.read()
os.startfile( outVid )

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

Пожалуйста, помогите. Спасибо


person Jay    schedule 21.11.2011    source источник


Ответы (5)


Этот ответ, вероятно, немного запоздал для вас, но вы можете указать несколько рисунков в одном файле, используя тег [in] и перечислив каждый текст рисования с помощью запятых. Это позволяет вам использовать несколько строк, если вы ориентируете каждый отрисовываемый текст с помощью соответствующих методов позиционирования. В вашем примере командная строка будет выглядеть примерно так (помещает первую строку в середину экрана и помещает каждую последующую строку на 25 пикселей вниз):

ffmpeg -i test_in.avi -vf "[in]drawtext=fontsize=20:fontcolor=White:fontfile='/Windows/Fonts/arial.ttf':text='onLine1':x=(w)/2:y=(h)/2, drawtext=fontsize=20:fontcolor=White:fontfile='/Windows/Fonts/arial.ttf':text='onLine2':x=(w)/2:y=((h)/2)+25, drawtext=fontsize=20:fontcolor=White:fontfile='/Windows/Fonts/arial.ttf':text='onLine3':x=(w)/2:y=((h)/2)+50[out]" -y test_out.avi
person Ben    schedule 21.06.2012

Глядя на исходный код в ffmpeg (vs_drawtext.c):

static inline int is_newline(uint32_t c)
{
    return c == '\n' || c == '\r' || c == '\f' || c == '\v';
}

поэтому вы можете попробовать вставить \f или \v в текстовую строку, которые соответствуют символам ^L или ^K. Например:

-filter_complex "[in] drawtext=fontsize=40:fontcolor=white:fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf:x=(w-tw)/2:y=(h-th)/2:box=1:[email protected]:text='two^Llines'[out]"

^L является фактическим символом Ctrl-L, а не ^ и L, очевидно.

person Howard Connellan    schedule 11.10.2012
comment
+1 за ссылку на исходный код. Добро пожаловать в Stack Overflow! - person GargantuChet; 11.10.2012
comment
Я не знаю, зависит ли это от версии или нет, но, насколько мне известно, нет способа контролировать расстояние между строками с помощью этого решения, и в итоге я использовал решение @Ben, контролируя расстояние с помощью h:{int} команда. В противном случае линии оказались бы нарисованными друг над другом или, по крайней мере, так близко, что это было бы нечитаемо. - person Bertrand Caron; 26.02.2015
comment
Чтобы ввести ^L в большинстве терминалов, вы можете сначала сделать Ctrl-V, а затем нажать Ctrl-L. - person neuro_sys; 11.04.2018
comment
Вот источник, если кто-то хочет взглянуть: github.com/FFmpeg/FFmpeg/blob/ - person Sreenikethan I; 29.01.2019
comment
я не могу заставить его работать с этим, может ли кто-нибудь прислать мне персонажей с другого сайта или что-то в этом роде? - person Gaspar; 20.12.2019
comment
Не работает (ffmpeg v4.3.1 на MacOS), на моем видео пишется two^Llines - person Vincent; 16.04.2021

Я просто добавил новые строки внутри команды, и ffmpeg обработал ее правильно.

ffmpeg -i input.avi -vf "[in]drawtext=fontsize=20:text='hello
world':x=(w)/2:y=(h)/2:fontcolor=white[out]" -y out.mp4

Никакие хаки Ctrl+L, Ctrl+K не нужны!

т.е. Я просто нажал Enter после «привет».

Вы можете сделать это, редактируя файл скрипта или даже в командной строке bash.

person Atento    schedule 22.11.2015

Мне удалось заставить это работать из командной строки, указав параметр «текстовый файл» и поместив свой текст в этот файл.

Дополнительные сведения см. на странице http://ffmpeg.org/libavfilter.html#drawtext. Используйте сборку ffmpeg N-35057-g2c44aed для Windows, но важно, чтобы у вас была последняя версия libavfilter.

person Irik Anderson    schedule 28.11.2011
comment
Да, у меня уже есть это в качестве обходного пути, но мне не нравится тот факт, что мой скрипт постоянно создает и удаляет файлы. Кстати, вы также можете вызвать флаг drawtext более одного раза и просто сместить текст по оси Y, чтобы создать новую строку. Я протестировал и заработал, но, как говорится в моем вопросе, я хотел бы добавить много строк с одним флагом drawtext и без необходимости создавать внешний файл. Спасибо, что нашли время ответить. Очень признателен :) - person Jay; 28.11.2011

ТЕКСТ=$(printf "$1")

В сценарии оболочки

С вашим текстом в качестве аргумента сценария оболочки, включая символы новой строки

person mightcouldb1    schedule 11.03.2020