Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/main/python/ttconv/imsc/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,22 @@

'''IMSC reader'''

import io
import logging
import typing
import xml.etree.ElementTree as et

import ttconv.imsc.elements as imsc_elements
import ttconv.model as model

LOGGER = logging.getLogger(__name__)


def to_model(xml_tree, progress_callback=lambda _: None) -> typing.Optional[model.ContentDocument]:
def to_model(data_file: typing.BinaryIO, _config=None, progress_callback=lambda _: None) -> typing.Optional[model.ContentDocument]:
'''Convers an IMSC document to the data model'''

xml_element = xml_tree.getroot()
text_stream = io.TextIOWrapper(data_file, encoding='utf-8')
xml_element = et.parse(text_stream).getroot()

if not imsc_elements.TTElement.is_instance(xml_element):
LOGGER.fatal("A tt element is not the root element")
Expand Down
7 changes: 4 additions & 3 deletions src/main/python/ttconv/imsc/writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,14 @@

def from_model(
model_doc: model.ContentDocument,
output: typing.BinaryIO,
config: typing.Optional[imsc_config.IMSCWriterConfiguration] = None,
progress_callback: typing.Callable[[numbers.Real], typing.NoReturn] = lambda _: None
):
'''Converts the data model to an IMSC document. The writer regularly the `progress_callback` function, if provided,
with a real between 0 and 1, indicating the relative progress of the process.
'''

et.register_namespace("", xml_ns.TTML)
et.register_namespace("ttp", xml_ns.TTP)
et.register_namespace("tts", xml_ns.TTS)
Expand Down Expand Up @@ -78,12 +79,12 @@ def from_model(
else:
time_format = TimeExpressionSyntaxEnum.clock_time

return et.ElementTree(
et.ElementTree(
imsc_elements.TTElement.from_model(
model_doc,
config.fps,
time_format,
progress_callback,
config.profile_signaling
)
)
).write(output, encoding="utf-8")
20 changes: 17 additions & 3 deletions src/main/python/ttconv/scc/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from __future__ import annotations

import logging
import typing
from typing import Optional

from ttconv.model import ContentDocument, Body, Div, CellResolutionType, ActiveAreaType
Expand All @@ -45,9 +46,11 @@
# SCC reader
#

def to_model(scc_content: str, config: Optional[SccReaderConfiguration] = None, progress_callback=lambda _: None):
def to_model(data_file: typing.BinaryIO, config: Optional[SccReaderConfiguration] = None, progress_callback=lambda _: None):
"""Converts a SCC document to the data model"""

scc_content = data_file.read().decode("utf-8")

document = ContentDocument()

# Safe area must be a 32x15 grid, that represents 80% of the root area
Expand Down Expand Up @@ -104,8 +107,19 @@ def to_model(scc_content: str, config: Optional[SccReaderConfiguration] = None,
return document


def to_disassembly(scc_content: str, show_channels = False) -> str:
"""Dumps an SCC document into the disassembly format"""
def to_disassembly(scc_content: str | bytes, show_channels = False) -> str:
"""Converts SCC content into a human-readable disassembly string.

Args:
scc_content: SCC file content as a string or UTF-8 encoded bytes.
show_channels: If True, include the channel number for each data word.

Returns:
A string with one disassembled line per SCC line, terminated by newlines.
"""
if isinstance(scc_content, bytes):
scc_content = scc_content.decode("utf-8")

disassembly = ""
for line in scc_content.splitlines():
LOGGER.debug(line)
Expand Down
5 changes: 3 additions & 2 deletions src/main/python/ttconv/scc/writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import logging
from fractions import Fraction
import re
import typing
from typing import List, Optional, Sequence

import ttconv.model as model
Expand Down Expand Up @@ -236,7 +237,7 @@ def _octet2hex(octet):
#
# scc writer
#
def from_model(doc: model.ContentDocument, config: Optional[SccWriterConfiguration] = None, progress_callback=lambda _: None) -> str:
def from_model(doc: model.ContentDocument, output: typing.BinaryIO, config: Optional[SccWriterConfiguration] = None, progress_callback=lambda _: None):
"""Converts the data model to an SCC document"""

# split progress between ISD construction and SCC writing
Expand Down Expand Up @@ -420,4 +421,4 @@ def _isd_progress(progress: float):
if start_offset + chunk.get_begin() < 0:
raise RuntimeError("The SCC stream would start earlier than the specified start timecode")

return "Scenarist_SCC V1.0\n\n" + "\n\n".join(map(lambda e: e.to_string(config.frame_rate.fps, config.frame_rate.df, start_offset), chunks))
output.write(b"Scenarist_SCC V1.0\n\n" + b"\n\n".join(map(lambda e: e.to_string(config.frame_rate.fps, config.frame_rate.df, start_offset).encode("utf-8"), chunks)))
5 changes: 3 additions & 2 deletions src/main/python/ttconv/srt/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from __future__ import annotations

import typing
import io
import re
import logging
from enum import Enum
Expand Down Expand Up @@ -208,7 +209,7 @@ class _State(Enum):
_DEFAULT_LINE_HEIGHT = styles.LengthType(125, styles.LengthType.Units.pct)
_DEFAULT_SAFE_AREA_PCT = 10

def to_model(data_file: typing.IO, _config: SRTReaderConfiguration = None, progress_callback=lambda _: None):
def to_model(data_file: typing.BinaryIO, _config: SRTReaderConfiguration = None, progress_callback=lambda _: None):
"""Converts an SRT document to the data model"""

extended_tags = _config.extended_tags if isinstance(_config, SRTReaderConfiguration) else False
Expand All @@ -235,7 +236,7 @@ def to_model(data_file: typing.IO, _config: SRTReaderConfiguration = None, progr

body.push_child(div)

lines : str = data_file.readlines()
lines : str = io.TextIOWrapper(data_file, encoding='utf-8').readlines()

state = _State.COUNTER
current_p = None
Expand Down
7 changes: 4 additions & 3 deletions src/main/python/ttconv/srt/writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"""SRT writer"""

import logging
import typing
from fractions import Fraction
from typing import List, Optional

Expand Down Expand Up @@ -186,8 +187,8 @@ def __str__(self) -> str:
#


def from_model(doc: model.ContentDocument, config: Optional[SRTWriterConfiguration] = None, progress_callback=lambda _: None) -> str:
"""Converts the data model to a SRT document"""
def from_model(doc: model.ContentDocument, output: typing.BinaryIO, config: Optional[SRTWriterConfiguration] = None, progress_callback=lambda _: None):
"""Converts the data model to a SRT document, writing the result to `output`."""

srt = SrtContext(config if config is not None else SRTWriterConfiguration())

Expand Down Expand Up @@ -217,4 +218,4 @@ def _isd_progress(progress: float):

srt.finish()

return str(srt)
output.write(str(srt).encode("utf-8"))
2 changes: 1 addition & 1 deletion src/main/python/ttconv/stl/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
# STL reader
#

def to_model(data_file: typing.IO, config: typing.Optional[STLReaderConfiguration] = None, progress_callback=lambda _: None):
def to_model(data_file: typing.BinaryIO, config: typing.Optional[STLReaderConfiguration] = None, progress_callback=lambda _: None):
"""Converts an STL document to the data model"""

m = DataFile(
Expand Down
51 changes: 18 additions & 33 deletions src/main/python/ttconv/tt.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,8 @@
import os
import sys
import typing
import xml.etree.ElementTree as et
from argparse import ArgumentParser
from enum import Enum
from pathlib import Path
from ttconv.filters.document_filter import DocumentFilter

import ttconv.imsc.reader as imsc_reader
Expand Down Expand Up @@ -300,28 +298,25 @@ def convert(args):
writer_type = FileTypes.get_file_type(args.otype, output_file_extension)

if reader_type is FileTypes.TTML:
#
# Parse the xml input file into an ElementTree
#
tree = et.parse(inputfile)

#
# Pass the parsed xml to the reader
# Open the file and pass it to the reader
#
model = imsc_reader.to_model(tree, progress_callback_read)
reader_config = read_config_from_json(IMSCWriterConfiguration, json_config_data)

elif reader_type is FileTypes.SCC:
file_as_str = Path(inputfile).read_text()
with open(inputfile, "rb") as f:
model = imsc_reader.to_model(f, reader_config, progress_callback_read)

elif reader_type is FileTypes.SCC:
#
# Read the config
#
reader_config = read_config_from_json(SccReaderConfiguration, json_config_data)

#
# Pass the parsed xml to the reader
# Open the file and pass it to the reader
#
model = scc_reader.to_model(file_as_str, reader_config, progress_callback_read)
with open(inputfile, "rb") as f:
model = scc_reader.to_model(f, reader_config, progress_callback_read)

elif reader_type is FileTypes.STL:
#
Expand All @@ -344,15 +339,15 @@ def convert(args):
#
# Open the file and pass it to the reader
#
with open(inputfile, "r", encoding="utf-8") as f:
with open(inputfile, "rb") as f:
model = srt_reader.to_model(f, reader_config, progress_callback_read)

elif reader_type is FileTypes.VTT:

#
# Open the file and pass it to the reader
#
with open(inputfile, "r", encoding="utf-8") as f:
with open(inputfile, "rb") as f:
model = vtt_reader.to_model(f, None, progress_callback_read)

else:
Expand Down Expand Up @@ -401,12 +396,11 @@ def convert(args):
#
# Construct and configure the writer
#
tree_from_model = imsc_writer.from_model(model, writer_config, progress_callback_write)

#
# Write out the converted file
#
tree_from_model.write(outputfile, encoding="utf-8")
with open(outputfile, "wb") as f:
imsc_writer.from_model(model, f, writer_config, progress_callback_write)

elif writer_type is FileTypes.SRT:
#
Expand All @@ -417,13 +411,8 @@ def convert(args):
#
# Construct and configure the writer
#
srt_document = srt_writer.from_model(model, writer_config, progress_callback_write)

#
# Write out the converted file
#
with open(outputfile, "w", encoding="utf-8") as srt_file:
srt_file.write(srt_document)
with open(outputfile, "wb") as srt_file:
srt_writer.from_model(model, srt_file, writer_config, progress_callback_write)

elif writer_type is FileTypes.VTT:
#
Expand All @@ -434,13 +423,11 @@ def convert(args):
#
# Construct and configure the writer
#
vtt_document = vtt_writer.from_model(model, writer_config, progress_callback_write)

#
# Write out the converted file
#
with open(outputfile, "w", encoding="utf-8") as vtt_file:
vtt_file.write(vtt_document)
with open(outputfile, "wb") as vtt_file:
vtt_writer.from_model(model, vtt_file, writer_config, progress_callback_write)

elif writer_type is FileTypes.SCC:
#
Expand All @@ -451,13 +438,11 @@ def convert(args):
#
# Construct and configure the writer
#
scc_document = scc_writer.from_model(model, writer_config, progress_callback_write)

#
# Write out the converted file
#
with open(outputfile, "w", encoding="utf-8") as scc_file:
scc_file.write(scc_document)
with open(outputfile, "wb") as scc_file:
scc_writer.from_model(model, scc_file, writer_config, progress_callback_write)


else:
Expand Down
5 changes: 3 additions & 2 deletions src/main/python/ttconv/vtt/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from __future__ import annotations

from dataclasses import dataclass
import io
import typing
import re
import logging
Expand Down Expand Up @@ -518,7 +519,7 @@ def vtt_timestamp_to_secs(vtt_ts: str):

return None

def to_model(data_file: typing.IO, _config = None, progress_callback=lambda _: None):
def to_model(data_file: typing.BinaryIO, _config = None, progress_callback=lambda _: None):
"""Converts a WebVTT document to the data model"""

class _State(Enum):
Expand All @@ -539,7 +540,7 @@ class _State(Enum):
div = model.Div(doc)
body.push_child(div)

lines : str = data_file.readlines()
lines : str = io.TextIOWrapper(data_file, encoding='utf-8').readlines()

state = _State.START
current_p = None
Expand Down
5 changes: 3 additions & 2 deletions src/main/python/ttconv/vtt/writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"""WebVTT writer"""

import logging
import typing
from fractions import Fraction
from typing import Dict, List, Optional

Expand Down Expand Up @@ -269,7 +270,7 @@ def __str__(self) -> str:
#


def from_model(doc: model.ContentDocument, config = None, progress_callback=lambda _: None) -> str:
def from_model(doc: model.ContentDocument, output: typing.BinaryIO, config=None, progress_callback=lambda _: None):
"""Converts the data model to a VTT document"""

# split progress between ISD construction and VTT writing
Expand All @@ -293,4 +294,4 @@ def _isd_progress(progress: float):

vtt.finish()

return str(vtt)
output.write(str(vtt).encode("utf-8"))
Loading