Текст в субтитрах отображается меньше, чем должен

Я добавляю субтитры к видео с помощью ffmpeg двумя разными способами. Первый способ — использовать команду drawtext, и в этом случае все работает отлично. Вот команда

ffmpeg -i ./input.mp4 -vf "drawtext=text='reise':fontfile=../fonts/Audiowide-Regular.ttf:fontsize=55:fontcolor=white:x=0:y=683" -codec:a copy ./output.mp4

Второй способ — использовать файл субтитров. Таким образом, я получил меньшие буквы и неправильное положение текста. Ниже приведено содержимое файла субтитров задницы.


[Script Info]
Title: Advanced Highlighted Subtitle Example
ScriptType: v4.00+
WrapStyle: 0
PlayResX: 1048
PlayResY: 750

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Audiowide Regular,55,&HFFFFFF,&H00FFFFFF,&H00000000,&H00000000,1,0,0,0,100,100,0,0,0,0,0,2,10,10,10,1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text

Dialogue: 0,00:00:0.00,00:00:2.38,Default,,0,0,0,,{\pos(0,683)\an4}reise

И команда для второго захода

ffmpeg -i ./input.mp4 -vf "ass=../subtitles.ass:fontsdir=../fonts/Audiowide-Regular.ttf"  ../output.mp4

Таким образом, они оба получают одно и то же видео, один и тот же шрифт и один и тот же текст. Проблема в том, что в случае использования файла ass текст становится намного меньше и смещается

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

Я попробовал решение от [universalmediaserver] для удаления PlayResX/Y, но оно не работает. (https://www.universalmediaserver.com/forum/viewtopic.php?t=5907). Я также пытался измерить ширину текста многими другими способами (например, в HTML, отображаемом в браузере, на холсте...), поэтому я почти уверен, что drawtext действительно дает правильно отображаемую ширину. Проблема связана с файлом субтитров. Кроме того, если я использую популярные шрифты, такие как Arial, отклонение будет намного меньше.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
62
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Фильтр drawtext FFmpeg интерпретирует размер шрифта текста иначе, чем средства рендеринга ASS (например, Libass). Фильтр drawtext использует номинальный размер шрифта (в пикселях), масштабируя его в соответствии с единицами на EM. Напротив, средства визуализации ASS используют реальные размеры шрифта для масштабирования, которые они определяют путем суммирования поля ascender и минусового значения поля descender из таблиц шрифта (таких как OS/2 и hhea).

Таким образом, чтобы сопоставить размер между drawtext и ASS в FFmpeg, нам нужно найти способ вычисления реального размера шрифта (ASS) из номинального размера (drawtext). Итак, давайте сначала рассчитаем базовый размер шрифта, который затем будет использоваться для его масштабирования.

Для номинального размера нам нужно прочитать unitsPerEm из Таблицы заголовков шрифтов, в случае шрифта Audiowide это 2048. Для реального размера измерения нам нужно получить значение полей ascender и descender, которые можно найти в таблице hhea, в случае шрифта Audiowide его верхний предел равен 2027, а нижний - -584.

Итак: Номинальный размер = unitsPerEm = 2048 Реальный размер измерения = ascender - descender = 2027 - (-584) = 2611

Таким образом, реальный размер измерения в некотором масштабе больше.

Масштаб = Реальный размер / Номинальный размер = 2611/2048 ≈ 1,279

Итак, нам нужно умножить исходный размер шрифта (55) на масштабный коэффициент: 55 * 1,279 ≈ 70,345.

Во-вторых, обратите внимание, что фильтр drawtext использует другое выравнивание, чем тег выравнивания \an4 в ASS, который вы использовали, что соответствует выравниванию по левому краю. Чтобы совместить позиции, вы должны использовать \an7 (выравнивание по левому краю) в ASS.

В-третьих, drawtext выравнивает текст по самому высокому глифу (по историческим причинам), а не по базовой линии плюс восхождение (как это обычно делается), но вы можете изменить это, установив y_align=font в фильтре drawtext.

Итак, вот исправленный файл сценария ASSv4+:

[Script Info]
Title: Advanced Highlighted Subtitle Example
ScriptType: v4.00+
WrapStyle: 0
PlayResX: 1048
PlayResY: 750

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding 
Style: Default,Audiowide,70.345,&H00FFFFFF,&H00FFFFFF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,0,2,10,10,10,1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text

Dialogue: 0,00:00:0.00,00:00:2.38,Default,,0,0,0,,{\pos(0,683)\an7}reise

И исправлена ​​команда FFmpeg:

ffmpeg -i ./input.mp4 -vf "drawtext=text='reise':fontfile=../fonts/Audiowide-Regular.ttf:fontsize=55:fontcolor=white:x=0:y=683:y_align=font" -codec:a copy ./output.mp4

Ниже приведен пример того, как читать значения метрик из шрифта с помощью Freetype (это то, что drawtext и средство рендеринга ASS Libass использует под капотом для рендеринга шрифтов) в Python:

import freetype

face = freetype.Face('path/to/your/fontfile.ttf')

units_per_em = face.units_per_EM
ascender = face.ascender
descender = face.descender

print(f"Units per EM: {units_per_em}")
print(f"Ascender: {ascender}")
print(f"Descender: {descender}")

Результат для шрифта Audiowide должен быть:

Units per EM: 2048
Ascender: 2027
Descender: -584

И вы можете установить необходимую библиотеку, используя:

python -m pip install freetype-py

Другие вопросы по теме