def render_typewriter_frames_old(
text: str,
out_dir: Path,
*,
width: int,
height: int,
fps: int = 25,
duration_s: float = 10.0,
chars_per_s: float = 18.0,
font_path: str = "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
font_size: int = 44,
margin: int = 80,
):
out_dir.mkdir(parents=True, exist_ok=True)
font = ImageFont.truetype(font_path, font_size)
total_frames = int(duration_s * fps)
for i in range(total_frames):
t = i / fps
n_chars = min(len(text), int(t * chars_per_s))
reveal = text[:n_chars]
# transparent frame
img = Image.new("RGBA", (width, height), (0, 0, 0, 0))
d = ImageDraw.Draw(img)
# simple text box (optional): semi-transparent rectangle
box_top = height - 320
d.rounded_rectangle(
[margin - 30, box_top - 30, width - margin + 30, height - margin + 30],
radius=24,
fill=(0, 0, 0, 140),
)
# draw revealed text
d.text((margin, box_top), reveal, font=font, fill=(255, 255, 255, 255))
# blinking cursor if not finished
if n_chars < len(text) and (int(t * 2) % 2 == 0):
# measure text width to place cursor
tw = d.textlength(reveal, font=font)
d.text((margin + tw + 2, box_top), "|", font=font, fill=(255, 255, 255, 255))
img.save(out_dir / f"tw_{i:05d}.png")
Это работало нормально, но многострочный текст отображался неправильно. Ошибка была:
"Невозможно измерить длину многострочного текста"
Как можно структурировать текст, чтобы можно было легко найти текущую позицию последнего слова (которая может меняться из-за разных размеров шрифта, ширины страницы и т. д.) и знать, где поместить курсор в самом новом фрейме?
Я использую Pillow для рендеринга текста для наложения для ввода в ffmpeg. Вот моя функция рендеринга: [code]def render_typewriter_frames_old( text: str, out_dir: Path, *, width: int, height: int, fps: int = 25, duration_s: float = 10.0, chars_per_s: float = 18.0, font_path: str = "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", font_size: int = 44, margin: int = 80, ): out_dir.mkdir(parents=True, exist_ok=True) font = ImageFont.truetype(font_path, font_size)
total_frames = int(duration_s * fps) for i in range(total_frames): t = i / fps n_chars = min(len(text), int(t * chars_per_s)) reveal = text[:n_chars]
# blinking cursor if not finished if n_chars < len(text) and (int(t * 2) % 2 == 0): # measure text width to place cursor tw = d.textlength(reveal, font=font) d.text((margin + tw + 2, box_top), "|", font=font, fill=(255, 255, 255, 255))
img.save(out_dir / f"tw_{i:05d}.png") [/code] Это работало нормально, но многострочный текст отображался неправильно. Ошибка была:
"Невозможно измерить длину многострочного текста"
Как можно структурировать текст, чтобы можно было легко найти текущую позицию последнего слова (которая может меняться из-за разных размеров шрифта, ширины страницы и т. д.) и знать, где поместить курсор в самом новом фрейме?