diff --git a/pycaption/__init__.py b/pycaption/__init__.py
index fe31a773..0539f613 100644
--- a/pycaption/__init__.py
+++ b/pycaption/__init__.py
@@ -7,6 +7,7 @@
from .microdvd import MicroDVDReader, MicroDVDWriter
from .sami import SAMIReader, SAMIWriter
from .scenarist import ScenaristDVDWriter
+from .filtergraph import FiltergraphWriter
from .srt import SRTReader, SRTWriter
from .scc import SCCReader, SCCWriter
from .scc.translator import translate_scc
@@ -22,8 +23,8 @@
'MicroDVDWriter', 'SAMIReader', 'SAMIWriter', 'SRTReader', 'SRTWriter',
'SCCReader', 'SCCWriter', 'translate_scc', 'WebVTTReader', 'WebVTTWriter',
'CaptionReadError', 'CaptionReadNoCaptions', 'CaptionReadSyntaxError',
- 'detect_format', 'CaptionNode', 'Caption', 'CaptionList', 'CaptionSet', 'ScenaristDVDWriter'
- 'TranscriptWriter'
+ 'detect_format', 'CaptionNode', 'Caption', 'CaptionList', 'CaptionSet',
+ 'ScenaristDVDWriter', 'FiltergraphWriter', 'TranscriptWriter'
]
SUPPORTED_READERS = (
diff --git a/pycaption/filtergraph.py b/pycaption/filtergraph.py
new file mode 100644
index 00000000..1de1a7d0
--- /dev/null
+++ b/pycaption/filtergraph.py
@@ -0,0 +1,130 @@
+import tempfile
+import zipfile
+from io import BytesIO
+
+from pycaption.base import CaptionSet
+from pycaption.subtitler_image_based import SubtitleImageBasedWriter
+
+
+class FiltergraphWriter(SubtitleImageBasedWriter):
+ """
+ FFmpeg filtergraph writer for image-based subtitles.
+
+ Generates PNG subtitle images and an FFmpeg filtergraph that can be used
+ to create a transparent WebM video with subtitle overlays.
+
+ By default, generates Full HD (1920x1080) images. The filtergraph uses
+ the overlay filter with timing to display each subtitle at the correct time.
+
+ Uses PNG format for images with 4-color indexed palette for optimal
+ compression (~6 KB per Full HD image).
+ """
+
+ def __init__(self, relativize=True, video_width=1920, video_height=1080,
+ fit_to_screen=True, frame_rate=25, output_dir=None):
+ """
+ Initialize the filtergraph writer.
+
+ :param relativize: Convert absolute positioning to percentages
+ :param video_width: Width of generated subtitle images (default: 1920 for Full HD)
+ :param video_height: Height of generated subtitle images (default: 1080 for Full HD)
+ :param fit_to_screen: Ensure captions fit within screen bounds
+ :param frame_rate: Frame rate for timing calculations
+ """
+ if output_dir is None:
+ self.output_dir = 'embedded_subs'
+ else:
+ self.output_dir = output_dir
+ super().__init__(relativize, video_width, video_height, fit_to_screen, frame_rate)
+
+ def save_image(self, tmp_dir, index, img):
+ """Save RGBA image as PNG with transparency."""
+ img.save(
+ tmp_dir + '/subtitle%04d.png' % index,
+ optimize=True,
+ compress_level=9
+ )
+
+ def format_ts_seconds(self, value):
+ """
+ Format timestamp as seconds with 3 decimal places for FFmpeg.
+
+ :param value: Time in microseconds
+ :return: Seconds as float string
+ """
+ return f"{value / 1_000_000:.3f}"
+
+ def write(
+ self,
+ caption_set: CaptionSet,
+ position='bottom',
+ avoid_same_next_start_prev_end=False,
+ align='center'
+ ):
+ """
+ Write captions as PNG images with an FFmpeg filtergraph for creating
+ a transparent WebM video overlay.
+
+ Returns a ZIP file containing:
+ - PNG subtitle images in the specified image_dir
+ - filtergraph.txt: FFmpeg filter_complex script
+
+ :param caption_set: CaptionSet containing the captions to write
+ :param position: Position of subtitles ('top', 'bottom', 'source')
+ :param avoid_same_next_start_prev_end: Adjust timing to avoid overlaps
+ :param align: Text alignment ('left', 'center', 'right')
+ :return: ZIP file contents as bytes
+ """
+ lang = caption_set.get_languages().pop()
+ caps = caption_set.get_captions(lang)
+
+ buf = BytesIO()
+ with tempfile.TemporaryDirectory() as tmpDir:
+ caps_final, overlapping = self.write_images(
+ caps, lang, tmpDir, position, align, avoid_same_next_start_prev_end
+ )
+
+ # Calculate total duration (last end time)
+ max_end = max(cap_list[0].end for cap_list in caps_final)
+ duration_seconds = max_end / 1_000_000 + 1 # Add 1 second buffer
+
+ # Build FFmpeg filtergraph
+ # Start with transparent base
+ filter_parts = []
+ filter_parts.append(
+ f"color=c=black@0:s={self.video_width}x{self.video_height}:d={duration_seconds:.3f},format=yuva444p[base]"
+ )
+
+ # Load each image (paths relative to where ffmpeg is run)
+ for i in range(1, len(caps_final) + 1):
+ filter_parts.append(
+ f"movie={self.output_dir}/subtitle{i:04d}.png,format=yuva444p[s{i}]"
+ )
+
+ # Chain overlays
+ prev_label = "base"
+ for i, cap_list in enumerate(caps_final, 1):
+ start_sec = self.format_ts_seconds(cap_list[0].start)
+ end_sec = self.format_ts_seconds(cap_list[0].end)
+ next_label = f"v{i}" if i < len(caps_final) else "out"
+
+ filter_parts.append(
+ f"[{prev_label}][s{i}]overlay=x=0:y=0:enable='between(t,{start_sec},{end_sec})':format=auto[{next_label}]"
+ )
+ prev_label = next_label
+
+ filtergraph = ";\n".join(filter_parts)
+
+
+ # Create ZIP archive
+ with zipfile.ZipFile(buf, 'w', zipfile.ZIP_DEFLATED) as zf:
+ # Add images
+ for i in range(1, len(caps_final) + 1):
+ img_path = tmpDir + '/subtitle%04d.png' % i
+ zf.write(img_path, f'{self.output_dir}/subtitle{i:04d}.png')
+
+ # Add filtergraph
+ zf.writestr(f'{self.output_dir}/filtergraph.txt', filtergraph)
+
+ buf.seek(0)
+ return buf.read()
diff --git a/pycaption/scenarist.py b/pycaption/scenarist.py
index a8b10876..b442bd4e 100644
--- a/pycaption/scenarist.py
+++ b/pycaption/scenarist.py
@@ -4,6 +4,8 @@
from datetime import timedelta
from io import BytesIO
+from PIL import Image
+
from pycaption.base import CaptionSet
from pycaption.subtitler_image_based import SubtitleImageBasedWriter
@@ -73,12 +75,22 @@ class ScenaristDVDWriter(SubtitleImageBasedWriter):
tiff_compression = None
+ # DVD subtitle palette colors
+ paColor = (255, 255, 255) # letter body (white)
+ e1Color = (190, 190, 190) # antialiasing color (gray)
+ e2Color = (0, 0, 0) # border color (black)
+ bgColor = (0, 255, 0) # background color (green - will be transparent on DVD)
+
def __init__(self, relativize=True, video_width=720, video_height=480, fit_to_screen=True, tape_type='NON_DROP',
frame_rate=25, compat=False):
super().__init__(relativize, video_width, video_height, fit_to_screen, frame_rate)
self.tape_type = tape_type
self.frame_rate = frame_rate
+ # Create palette image for quantization (4 colors only - smaller output)
+ self.palette_image = Image.new("P", (1, 1))
+ self.palette_image.putpalette([*self.paColor, *self.e1Color, *self.e2Color, *self.bgColor])
+
if compat:
self.color = '(1 2 3 4)'
self.contrast = '(15 15 15 0)'
@@ -87,7 +99,14 @@ def __init__(self, relativize=True, video_width=720, video_height=480, fit_to_sc
self.contrast = '(7 7 7 7)'
def save_image(self, tmp_dir, index, img):
- img.save(tmp_dir + '/subtitle%04d.tif' % index, compression=self.tiff_compression)
+ """Convert RGBA to paletted image for DVD subtitles."""
+ # Replace transparent pixels with green background
+ background = Image.new('RGB', img.size, self.bgColor)
+ background.paste(img, mask=img.split()[3]) # Use alpha channel as mask
+
+ # Quantize to 4-color palette
+ img_quant = background.quantize(palette=self.palette_image, dither=0)
+ img_quant.save(tmp_dir + '/subtitle%04d.tif' % index, compression=self.tiff_compression)
def write(
self,
diff --git a/pycaption/subtitler_image_based.py b/pycaption/subtitler_image_based.py
index d9d423e5..88eba71f 100644
--- a/pycaption/subtitler_image_based.py
+++ b/pycaption/subtitler_image_based.py
@@ -30,22 +30,14 @@ def get_sst_pixel_display_params(video_width, video_height):
class SubtitleImageBasedWriter(BaseWriter):
VALID_POSITION = ['top', 'bottom', 'source']
- paColor = (255, 255, 255) # letter body
- e1Color = (190, 190, 190) # antialiasing color
- e2Color = (0, 0, 0) # border color
- bgColor = (0, 255, 0) # background color
-
- palette_image = Image.new("P", (1, 1))
- palette_image.putpalette([*paColor, *e1Color, *e2Color, *bgColor] + [0, 0, 0] * 252)
+ # Default colors for RGBA rendering
+ fontColor = (255, 255, 255) # white text
+ borderColor = (0, 0, 0) # black border
def __init__(self, relativize=True, video_width=720, video_height=480, fit_to_screen=True, frame_rate=25):
super().__init__(relativize, video_width, video_height, fit_to_screen)
- self.palette = [self.paColor, self.e1Color, self.e2Color, self.bgColor]
self.frame_rate = frame_rate
- palette_image = Image.new("P", (1, 1))
- palette_image.putpalette([*self.paColor, *self.e1Color, *self.e2Color, *self.bgColor] + [0, 0, 0] * 252)
-
self.font_langs = {
Language.get('en'): {'fontfile': f"{os.path.dirname(__file__)}/NotoSansDisplay-Regular-Note-Math.ttf"},
Language.get('ru'): {'fontfile': f"{os.path.dirname(__file__)}/NotoSansDisplay-Regular-Note-Math.ttf"},
@@ -217,21 +209,21 @@ def write_images(
if missing_glyphs:
raise ValueError(f'Selected font was missing glyphs: {" ".join(missing_glyphs.keys())}')
- font_size = int(self.video_width * 0.05 * 0.6) # rough estimate but should work
+ min_font_px = 16
+ font_size = max(min_font_px, int(self.video_width * 0.05 * 0.6)) # rough estimate but should work
fnt = ImageFont.truetype(fnt, font_size)
index = 1
for i, cap_list in enumerate(caps_final):
- img = Image.new('RGB', (self.video_width, self.video_height), self.bgColor)
+ # Create RGBA image with transparent background
+ img = Image.new('RGBA', (self.video_width, self.video_height), (0, 0, 0, 0))
draw = ImageDraw.Draw(img)
self.printLine(draw, cap_list, fnt, position, align)
- # quantize the image to our palette
- img_quant = img.quantize(palette=self.palette_image, dither=0)
- self.save_image(tmpDir, index, img_quant)
-
+ # Pass RGBA image to subclass - each subclass converts as needed
+ self.save_image(tmpDir, index, img)
index = index + 1
@@ -285,25 +277,25 @@ def printLine(self, draw: ImageDraw, caption_list: Caption, fnt: ImageFont, posi
else:
raise ValueError('Unknown "position": {}'.format(position))
- borderColor = self.e2Color
- fontColor = self.paColor
+ border = (*self.borderColor, 255) # Add alpha for RGBA
+ font = (*self.fontColor, 255) # Add alpha for RGBA
for adj in range(2):
# move right
- draw.text((x - adj, y), text, font=fnt, fill=borderColor, align=align)
+ draw.text((x - adj, y), text, font=fnt, fill=border, align=align)
# move left
- draw.text((x + adj, y), text, font=fnt, fill=borderColor, align=align)
+ draw.text((x + adj, y), text, font=fnt, fill=border, align=align)
# move up
- draw.text((x, y + adj), text, font=fnt, fill=borderColor, align=align)
+ draw.text((x, y + adj), text, font=fnt, fill=border, align=align)
# move down
- draw.text((x, y - adj), text, font=fnt, fill=borderColor, align=align)
+ draw.text((x, y - adj), text, font=fnt, fill=border, align=align)
# diagnal left up
- draw.text((x - adj, y + adj), text, font=fnt, fill=borderColor, align=align)
+ draw.text((x - adj, y + adj), text, font=fnt, fill=border, align=align)
# diagnal right up
- draw.text((x + adj, y + adj), text, font=fnt, fill=borderColor, align=align)
+ draw.text((x + adj, y + adj), text, font=fnt, fill=border, align=align)
# diagnal left down
- draw.text((x - adj, y - adj), text, font=fnt, fill=borderColor, align=align)
+ draw.text((x - adj, y - adj), text, font=fnt, fill=border, align=align)
# diagnal right down
- draw.text((x + adj, y - adj), text, font=fnt, fill=borderColor, align=align)
+ draw.text((x + adj, y - adj), text, font=fnt, fill=border, align=align)
- draw.text((x, y), text, font=fnt, fill=fontColor, align=align)
+ draw.text((x, y), text, font=fnt, fill=font, align=align)
lines_written += 1
diff --git a/pycaption/ttml_background.py b/pycaption/ttml_background.py
index 1be44967..155341a2 100644
--- a/pycaption/ttml_background.py
+++ b/pycaption/ttml_background.py
@@ -45,15 +45,31 @@
class TTMLBackgroundWriter(SubtitleImageBasedWriter):
+ # Palette colors for TTML background images
+ paColor = (255, 255, 255) # letter body (white)
+ e1Color = (190, 190, 190) # antialiasing color (gray)
+ e2Color = (0, 0, 0) # border color (black)
+ bgColor = (0, 255, 0) # background color (green - index 3 = transparent)
+
def __init__(self, relativize=True, video_width=720, video_height=480, fit_to_screen=True, tape_type='NON_DROP',
frame_rate=25, compat=False):
super().__init__(relativize, video_width, video_height, fit_to_screen, frame_rate)
self.tape_type = tape_type
self.frame_rate = frame_rate
+ # Create palette image for quantization (4 colors only - smaller output)
+ self.palette_image = Image.new("P", (1, 1))
+ self.palette_image.putpalette([*self.paColor, *self.e1Color, *self.e2Color, *self.bgColor])
+
def save_image(self, tmp_dir, index, img):
- # Jetzt speichern mit Transparenz
- img.save(tmp_dir + '/subtitle%04d.png' % index, transparency=3)
+ """Convert RGBA to paletted PNG with transparency."""
+ # Replace transparent pixels with green background
+ background = Image.new('RGB', img.size, self.bgColor)
+ background.paste(img, mask=img.split()[3]) # Use alpha channel as mask
+
+ # Quantize to 4-color palette
+ img_quant = background.quantize(palette=self.palette_image, dither=0)
+ img_quant.save(tmp_dir + '/subtitle%04d.png' % index, transparency=3)
def to_ttml_timestamp(self, ms: int) -> str:
hours = ms // 3_600_000
diff --git a/test.py b/test.py
index f05ff39a..b51b922f 100644
--- a/test.py
+++ b/test.py
@@ -4,6 +4,7 @@
srtReader = SRTReader()
-c = srtReader.read(content=open("a.srt", "rb").read().decode('UTF-8-SIG'), lang='zh-Hans')
+c = srtReader.read(content=open("cookoff-1080p-h264-tidpix.srt", "rb").read().decode('UTF-8-SIG'), lang='zh-Hans')
w = ScenaristDVDWriter()
-w.write(c)
+open("cookoff-1080p-h264-tidpix.zip", "wb").write(w.write(c))
+
diff --git a/tests/test_filtergraph.py b/tests/test_filtergraph.py
new file mode 100644
index 00000000..d1fae66e
--- /dev/null
+++ b/tests/test_filtergraph.py
@@ -0,0 +1,138 @@
+import zipfile
+from io import BytesIO
+
+from pycaption import SRTReader
+from pycaption.filtergraph import FiltergraphWriter
+
+
+class TestFiltergraphWriterTestCase:
+ """Tests for the FiltergraphWriter that generates FFmpeg filtergraphs."""
+
+ def setup_method(self):
+ self.writer = FiltergraphWriter()
+
+ def test_zip_contents(self):
+ """Test that write returns a ZIP with correct contents."""
+ srt_content = """1
+00:00:01,000 --> 00:00:04,000
+Hello World
+
+2
+00:00:05,000 --> 00:00:08,000
+Second subtitle
+"""
+ caption_set = SRTReader().read(srt_content)
+ zip_data = self.writer.write(caption_set)
+
+ with zipfile.ZipFile(BytesIO(zip_data), 'r') as zf:
+ names = zf.namelist()
+ assert 'embedded_subs/subtitle0001.png' in names
+ assert 'embedded_subs/subtitle0002.png' in names
+ assert 'embedded_subs/filtergraph.txt' in names
+
+ def test_filtergraph_structure(self):
+ """Test that filtergraph has correct structure."""
+ srt_content = """1
+00:00:01,000 --> 00:00:04,000
+Test
+"""
+ caption_set = SRTReader().read(srt_content)
+ zip_data = self.writer.write(caption_set)
+
+ with zipfile.ZipFile(BytesIO(zip_data), 'r') as zf:
+ filtergraph = zf.read('embedded_subs/filtergraph.txt').decode()
+
+ # Should have color source for transparent base
+ assert 'color=c=black@0:s=1920x1080' in filtergraph
+ assert 'format=yuva444p' in filtergraph
+
+ # Should have movie input for image (path relative to ffmpeg working dir)
+ assert 'movie=embedded_subs/subtitle0001.png' in filtergraph
+
+ # Should have overlay with timing
+ assert 'overlay=x=0:y=0:enable=' in filtergraph
+ assert "between(t,1.000,4.000)" in filtergraph
+
+ def test_custom_output_dir(self):
+ """Test custom output directory."""
+ writer = FiltergraphWriter(output_dir='subs')
+ srt_content = """1
+00:00:01,000 --> 00:00:04,000
+Test
+"""
+ caption_set = SRTReader().read(srt_content)
+ zip_data = writer.write(caption_set)
+
+ with zipfile.ZipFile(BytesIO(zip_data), 'r') as zf:
+ names = zf.namelist()
+ assert 'subs/subtitle0001.png' in names
+ assert 'subs/filtergraph.txt' in names
+
+ filtergraph = zf.read('subs/filtergraph.txt').decode()
+ assert 'movie=subs/subtitle0001.png' in filtergraph
+
+ def test_multiple_overlays_chained(self):
+ """Test that multiple subtitles are chained correctly."""
+ srt_content = """1
+00:00:01,000 --> 00:00:04,000
+First
+
+2
+00:00:05,000 --> 00:00:08,000
+Second
+
+3
+00:00:10,000 --> 00:00:13,000
+Third
+"""
+ caption_set = SRTReader().read(srt_content)
+ zip_data = self.writer.write(caption_set)
+
+ with zipfile.ZipFile(BytesIO(zip_data), 'r') as zf:
+ filtergraph = zf.read('embedded_subs/filtergraph.txt').decode()
+
+ # Should have 3 movie inputs
+ assert 'movie=embedded_subs/subtitle0001.png' in filtergraph
+ assert 'movie=embedded_subs/subtitle0002.png' in filtergraph
+ assert 'movie=embedded_subs/subtitle0003.png' in filtergraph
+
+ # Should have chained overlays
+ assert '[base][s1]overlay' in filtergraph
+ assert '[v1][s2]overlay' in filtergraph
+ assert '[v2][s3]overlay' in filtergraph
+
+ # Last one should output to [out]
+ assert '[out]' in filtergraph
+
+ def test_duration_calculation(self):
+ """Test that duration is calculated from last subtitle end time."""
+ srt_content = """1
+00:00:01,000 --> 00:00:04,000
+First
+
+2
+00:01:30,000 --> 00:01:35,500
+Last one at 1:35
+"""
+ caption_set = SRTReader().read(srt_content)
+ zip_data = self.writer.write(caption_set)
+
+ with zipfile.ZipFile(BytesIO(zip_data), 'r') as zf:
+ filtergraph = zf.read('embedded_subs/filtergraph.txt').decode()
+
+ # Duration should be ~96.5 seconds (95.5 + 1 buffer)
+ assert 'd=96.500' in filtergraph
+
+ def test_custom_resolution(self):
+ """Test custom video resolution."""
+ writer = FiltergraphWriter(video_width=1280, video_height=720)
+ srt_content = """1
+00:00:01,000 --> 00:00:04,000
+Test
+"""
+ caption_set = SRTReader().read(srt_content)
+ zip_data = writer.write(caption_set)
+
+ with zipfile.ZipFile(BytesIO(zip_data), 'r') as zf:
+ filtergraph = zf.read('embedded_subs/filtergraph.txt').decode()
+ assert 's=1280x720' in filtergraph
diff --git a/tests/test_ttml_background.py b/tests/test_ttml_background.py
index c3920dce..2f7fa5ea 100644
--- a/tests/test_ttml_background.py
+++ b/tests/test_ttml_background.py
@@ -1,3 +1,6 @@
+import base64
+import re
+
from pycaption import (DFXPReader, SRTReader)
from pycaption.ttml_background import TTMLBackgroundWriter
@@ -7,71 +10,99 @@ class TestTTMLBackgroundWriterTestCase:
def setup_class(self):
self.writer = TTMLBackgroundWriter()
+ def _validate_ttml_structure(self, results, expected_num_images, expected_timings):
+ """Validate TTML structure and content."""
+ # Check XML header and namespaces
+ assert "" in results
+ assert 'xmlns:smpte="http://www.smpte-ra.org/schemas/2052-1/2010/smpte-tt"' in results
+ assert 'ttp:profile="http://www.w3.org/ns/ttml/profile/imsc1/image"' in results
+
+ # Check for correct number of images
+ image_pattern = r'(.*?)'
+ images = re.findall(image_pattern, results, re.DOTALL)
+ assert len(images) == expected_num_images, f"Expected {expected_num_images} images, got {len(images)}"
+
+ # Verify each image is valid base64 PNG
+ for img_id, img_data in images:
+ try:
+ decoded = base64.b64decode(img_data)
+ # Check PNG magic bytes
+ assert decoded[:8] == b'\x89PNG\r\n\x1a\n', f"Image {img_id} is not a valid PNG"
+ except Exception as e:
+ raise AssertionError(f"Image {img_id} is not valid base64: {e}")
+
+ # Check for correct div elements with timing
+ div_pattern = r'
'
+ divs = re.findall(div_pattern, results)
+ assert len(divs) == expected_num_images, f"Expected {expected_num_images} divs, got {len(divs)}"
+
+ # Verify timings
+ for i, (begin, end, img_id) in enumerate(divs):
+ expected_begin, expected_end = expected_timings[i]
+ assert begin == expected_begin, f"Div {i+1}: expected begin={expected_begin}, got {begin}"
+ assert end == expected_end, f"Div {i+1}: expected end={expected_end}, got {end}"
+ assert img_id == str(i + 1), f"Div {i+1}: expected img_id={i+1}, got {img_id}"
+
def test_arabic(self, sample_srt_arabic):
caption_set = SRTReader().read(sample_srt_arabic, lang='ar')
results = self.writer.write(caption_set)
- print(results)
- assert results == """
-
-
-
-
-
-
-iVBORw0KGgoAAAANSUhEUgAAAtAAAAHgCAMAAAC7G6qeAAADAFBMVEX///++vr4AAAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDvjs2AAAABHRSTlP///8AQCqp9AAACXBJREFUeJzt3Qly2kgAQFEk3//OE6MFgdkEsafy/V5lsoDUTqq+242Meg4fEHL4v/8C8DcJmhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJ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kyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQI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0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQp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JkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmC/o7x6k85Cy8J+mvXDofhHUG/5Sy8JOgvXXO+XN4S9CjojxP0F6acrz1/meI35gkjx+cJ+rVlef5GiOPXRxmiP0/Qr117XkMdZ48HrFu+nJBvk/jr6M+vsO759mP+qwn6tfFyORb7FO04Hnr/4lTz7PLyiJMrbHu+/Zj/aoL+iWWtPK7Qw1bveFiXl0Z/urjuJ7weOZwVvd3zcIXDznXP851+5f+rTtCnbu/UzSWP2xq9Jzu9jbcXPd28zRPDq8imA8dD0OO2tK9PmpMnxfLOyMmo85Y3XnoEfWZ+KXhZWtqmjq3nyz48rI1O2y4vkp6Ou1V9t2E+27Cfbdz+muJeZ429/uWH9YnEPUGfWNbMJb59qlgTvy3Fe+VzWdPiOrxIerrH7Y/jhvX5si3z0xXmZXlqeXkQ16OWhzDvWf4F+ehv4f9J0CduYd76XGeNLeQlt3nnwxI93RwPr/seyp5eE16OQU8Vz5PIeH+FqeLjkr49uaZt0wMzc5wS9LMpy0Oz63K8FDivnMeg9yF7OM4i+xixDArXKftuhp6W88va7XaFOd9xvNuxjifbNkGfEvSz2zp5WWaO2TxJLH8NW+3jcc443FrPst1YD70ffJdhY7nUcHeh9VXpvmO5/7D9IOgzgn42ZXfr7PbfbVW9DMu4sN0ahiXGYd4wH3Y3QB+DXo64/07IuL6O3C/1cIXpj+3y6zWG/QH8/t/NH0/Qz8Z1IR7WFpcfh209XdbNYV9fL4/v2h1H62F9NtwdcLvP/aUOV1g2TR+1rFu2w779efzfR9DPlldeRw8/LmPxyaaHsyw39+HlsH8dI87O/S2/8Vfy/yHoZ++ZTueIf2wf0jzs9b7bZwj62fHTj39xlvUV3ngy777tO9Y8EPSz9wS9j84n8+5oBv4QQT9716fK0+I8v1Z8+ibGy6998OsE/ex9b/H+9NWbnD9F0Cc+HzSfIugTb/s6/c+/sc+HCPrE21bVs2/s81GC/iQTx28naFIETYqgSRE0KYImRdCkCJoUQZMiaFL+AaVuyauPhcHlAAAAAElFTkSuQmCC
-
-
-
-
-
-
-
-
-"""
+
+ expected_timings = [
+ ("00:00:40.000", "00:00:43.250"),
+ ("00:00:44.542", "00:00:49.500"),
+ ("00:00:51.125", "00:00:54.417"),
+ ("00:00:55.292", "00:00:58.917"),
+ ]
+ self._validate_ttml_structure(results, 4, expected_timings)
def test_styling(self, sample_dfxp_from_sami_with_positioning):
caption_set = DFXPReader().read(sample_dfxp_from_sami_with_positioning)
results = self.writer.write(caption_set)
- print(results)
- assert results == """
-
-
-
-
-
-
-iVBORw0KGgoAAAANSUhEUgAAAtAAAAHgCAMAAAC7G6qeAAADAFBMVEX///++vr4AAAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDvjs2AAAABHRSTlP///8AQCqp9AAAB0NJREFUeJzt29FymzgAQFGb/P8/b2IMFjFulGyn7dw55yFjI4HzcEMFuJc3CLn87V8AfidBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQp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RdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0U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RdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0KYImRdCkCJoUQZMiaFIETYqgSRE0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NCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2K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ETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF0EQRNFEETRRBE0XQRBE0UQRNFEETRdBEETRRBE0UQRNF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FEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQpAiaFEGTImhSBE2KoEkRNCmCJkXQ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0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUgRNiqBJETQpgiZF0KQImhRBkyJoUu4c9Pztw9bnH+Zl63zndvMfdxnG/3S88d+fxzkN8ukYH57iLd066Mc0Bjatm/vN2w/z911P0zPd053z6/bXv+tDp8fbLvvwz4fO4/FeW/Nj+Pdy6O9hpmGY6+ZyiGmpeL3n+D3uSdDbxhble1XTs5pvj/egX/UsYc/rY9922Yafnreegp7m8bjPkc6HnrdxltEvm6/T6FX485q83jOvz/+2F+mbBr28PJ+C/u5rzeZa1VLM+np+uXPd5/HY43/bZRt+nk8Xz3kfYTvMe9Cv02XJdZ6vm8spsJ5T+13rQNNdi75l0K8K3oOej7KWm5bt80Thh6DXi/Ea9GmXffhz0K9HPe+Yln1Oz+hy6GXHy+bphLu8FszjbOdWbhj0fEwULtfL6UPQ5+x/DvrYvu5yjL/NsNeb9jnMevm9Bn30v+09bh5Tok9Br5fsf/B/23/E7YIe/tanoKetih+r2m8b5itD0NP66B/elj1vvAy1PI/1XNj/c4w+VnqJdrm4D3OVo99tDn3TpO8W9OlPPwb92C6Q70Fva2Hz8vZvWlyDXkZYgx532Q782N7anS6l24m0rZoMo48FT+egpy3obR6zTMXH9wD7C9G93C7oYXI5BL2/Tv8Y9LYo9thdg562ScVll+0AS9DP92vHc3kuxB1RX0b/PehllWNaht3W847nP8/jsso93C7o/Up2Dnragv4wkZ23926P66TgFPQW3XWX11DLKvN2Dd8Pup5IrxnLcc39MOX4Iei3RerjrcE8bwsot3K3oJe/+9scej4ujHvQ83XKsQW97nEJ+mvv8rLL69HrqfIYL5qvs2h/YzidLq5/O4c+z2qmYzY+j6fujdwu6G1yOQ1xbjOO82re+5T6z0G/Nq6Tlsf4w2s17TzP2ZfsPgf9N6sc42/2eorrzPqOOd8y6K/3dej1ArrOg49P/c6Lwb8G/er1bZfhhzWz/Xk858DLKOM4x+h/sw59+sVeT3G55t/v/eDLLYPeViD2Gevporx/6rZHeHw+98egl+9rzNddvoZBptP3OYZPCddjvY3+2yeFp99neydwmojczE2DftkXyYYX8+XKvX5jYtquh+sXM96CvnxEc4Q57vK13rOsxo1LafP4rYxPQc+/fJdjeA+wHe7yceTt3DzoxbHysK92DN+U27bP8+5t3fgxZr5f1cdd1kG2Mc+T6Mc4h7gG/eu37cZVmv37gIK+q3l03Hbc8fbAr///+9CfDnb+LvR199Nul1HODzof7r7Tjac7B02QoEkRNCmCJkXQpAiaFEGTImhSBE2KoEn5H/VQwYklqsiwAAAAAElFTkSuQmCC
-
-
-
-
-
-
-
-
-
-
-
-"""
+
+ expected_timings = [
+ ("00:00:09.209", "00:00:12.312"),
+ ("00:00:14.848", "00:00:17.000"),
+ ("00:00:17.000", "00:00:18.752"),
+ ("00:00:18.752", "00:00:20.887"),
+ ("00:00:20.887", "00:00:26.760"),
+ ("00:00:26.760", "00:00:32.200"),
+ ("00:00:32.200", "00:00:36.200"),
+ ]
+ self._validate_ttml_structure(results, 7, expected_timings)
+
+ def test_simple_srt(self):
+ """Test basic SRT conversion to TTML with images."""
+ srt_content = """1
+00:00:01,000 --> 00:00:04,000
+Hello World
+
+2
+00:00:05,000 --> 00:00:08,000
+Second subtitle
+"""
+ caption_set = SRTReader().read(srt_content)
+ results = self.writer.write(caption_set)
+
+ expected_timings = [
+ ("00:00:01.000", "00:00:04.000"),
+ ("00:00:05.000", "00:00:08.000"),
+ ]
+ self._validate_ttml_structure(results, 2, expected_timings)
+
+ def test_image_transparency(self):
+ """Test that generated images have proper transparency (index 3)."""
+ srt_content = """1
+00:00:01,000 --> 00:00:04,000
+Test
+"""
+ caption_set = SRTReader().read(srt_content)
+ results = self.writer.write(caption_set)
+
+ # Extract image
+ image_pattern = r']*>(.*?)'
+ match = re.search(image_pattern, results, re.DOTALL)
+ assert match is not None
+
+ # Decode and verify it's a PNG
+ decoded = base64.b64decode(match.group(1))
+ assert decoded[:8] == b'\x89PNG\r\n\x1a\n'