Skip to content

Commit

Permalink
Added DFXP, SBV, SUB sync map output formats. Marked Czech as tested.
Browse files Browse the repository at this point in the history
  • Loading branch information
Alberto Pettarin committed Jan 20, 2016
1 parent 7104f14 commit 7d6372d
Show file tree
Hide file tree
Showing 16 changed files with 632 additions and 21 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.4.0
1.4.1
4 changes: 2 additions & 2 deletions aeneas/language.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
Copyright 2015-2016, Alberto Pettarin (www.albertopettarin.it)
"""
__license__ = "GNU AGPL v3"
__version__ = "1.4.0"
__version__ = "1.4.1"
__email__ = "[email protected]"
__status__ = "Production"

Expand Down Expand Up @@ -40,7 +40,7 @@ class Language(object):
""" Catalan """

CS = "cs"
""" Czech (not tested) """
""" Czech """

CY = "cy"
""" Welsh """
Expand Down
151 changes: 133 additions & 18 deletions aeneas/syncmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
Copyright 2015-2016, Alberto Pettarin (www.albertopettarin.it)
"""
__license__ = "GNU AGPL v3"
__version__ = "1.4.0"
__version__ = "1.4.1"
__email__ = "[email protected]"
__status__ = "Production"

Expand Down Expand Up @@ -86,6 +86,11 @@ class SyncMapFormat(object):
.. versionadded:: 1.2.0
"""

DFXP = "dfxp"
"""
Alias for TTML
"""

JSON = "json"
"""
JSON::
Expand Down Expand Up @@ -147,6 +152,25 @@ class SyncMapFormat(object):
.. versionadded:: 1.2.0
"""

SBV = "sbv"
"""
SubViewer (SBV/SUB) caption/subtitle format,
with multiple lines per fragment are separated by a newline character::
[SUBTITLE]
00:00:00.000,00:00:01.234
First fragment text
00:00:01.234,00:00:05.678
Second fragment text
Second line of second fragment
00:00:05.678,00:00:07.890
Third fragment text
Second line of third fragment
"""

SMIL = "smil"
"""
Alias for SMILH
Expand Down Expand Up @@ -208,7 +232,7 @@ class SyncMapFormat(object):

SRT = "srt"
"""
SRT caption/subtitle format
SubRip (SRT) caption/subtitle format
(it might have multiple lines per fragment)::
1
Expand Down Expand Up @@ -262,6 +286,23 @@ class SyncMapFormat(object):
.. versionadded:: 1.2.0
"""

SUB = "sub"
"""
SubViewer (SBV/SUB) caption/subtitle format,
with multiple lines per fragment are separated by [br]::
[SUBTITLE]
00:00:00.000,00:00:01.234
First fragment text
00:00:01.234,00:00:05.678
Second fragment text[br]Second line of second fragment
00:00:05.678,00:00:07.890
Third fragment text[br]Second line of third fragment
"""

TAB = "tab"
"""
Deprecated, it will be removed in v2.0.0. Use TSV instead.
Expand Down Expand Up @@ -433,15 +474,18 @@ class SyncMapFormat(object):
CSV,
CSVH,
CSVM,
DFXP,
JSON,
RBSE,
SBV,
SMIL,
SMILH,
SMILM,
SRT,
SSV,
SSVH,
SSVM,
SUB,
TAB,
TSV,
TSVH,
Expand Down Expand Up @@ -656,15 +700,18 @@ def read(self, sync_map_format, input_file_path, parameters=None):
SyncMapFormat.CSV: partial(self._read_csv, parse_time=gf.time_from_ssmmm),
SyncMapFormat.CSVH: partial(self._read_csv, parse_time=gf.time_from_hhmmssmmm),
SyncMapFormat.CSVM: partial(self._read_csv, parse_time=gf.time_from_ssmmm),
SyncMapFormat.DFXP: self._read_ttml,
SyncMapFormat.JSON: self._read_json,
SyncMapFormat.RBSE: self._read_rbse,
SyncMapFormat.SBV: partial(self._read_sub, use_newline=True),
SyncMapFormat.SMIL: self._read_smil,
SyncMapFormat.SMILH: self._read_smil,
SyncMapFormat.SMILM: self._read_smil,
SyncMapFormat.SRT: self._read_srt,
SyncMapFormat.SSV: partial(self._read_ssv, parse_time=gf.time_from_ssmmm),
SyncMapFormat.SSVH: partial(self._read_ssv, parse_time=gf.time_from_hhmmssmmm),
SyncMapFormat.SSVM: partial(self._read_ssv, parse_time=gf.time_from_ssmmm),
SyncMapFormat.SUB: partial(self._read_sub, use_newline=False),
SyncMapFormat.TAB: partial(self._read_tsv, parse_time=gf.time_from_ssmmm),
SyncMapFormat.TSV: partial(self._read_tsv, parse_time=gf.time_from_ssmmm),
SyncMapFormat.TSVH: partial(self._read_tsv, parse_time=gf.time_from_hhmmssmmm),
Expand Down Expand Up @@ -722,15 +769,18 @@ def write(self, sync_map_format, output_file_path, parameters=None):
SyncMapFormat.CSV: partial(self._write_csv, format_time=gf.time_to_ssmmm),
SyncMapFormat.CSVH: partial(self._write_csv, format_time=gf.time_to_hhmmssmmm),
SyncMapFormat.CSVM: partial(self._write_csv, format_time=gf.time_to_ssmmm),
SyncMapFormat.DFXP: partial(self._write_ttml, parameters=parameters),
SyncMapFormat.JSON: self._write_json,
SyncMapFormat.RBSE: self._write_rbse,
SyncMapFormat.SBV: partial(self._write_sub, use_newline=True),
SyncMapFormat.SMIL: partial(self._write_smil, format_time=gf.time_to_hhmmssmmm, parameters=parameters),
SyncMapFormat.SMILH: partial(self._write_smil, format_time=gf.time_to_hhmmssmmm, parameters=parameters),
SyncMapFormat.SMILM: partial(self._write_smil, format_time=gf.time_to_ssmmm, parameters=parameters),
SyncMapFormat.SRT: self._write_srt,
SyncMapFormat.SSV: partial(self._write_ssv, format_time=gf.time_to_ssmmm),
SyncMapFormat.SSVH: partial(self._write_ssv, format_time=gf.time_to_hhmmssmmm),
SyncMapFormat.SSVM: partial(self._write_ssv, format_time=gf.time_to_ssmmm),
SyncMapFormat.SUB: partial(self._write_sub, use_newline=False),
SyncMapFormat.TAB: partial(self._write_tsv, format_time=gf.time_to_ssmmm),
SyncMapFormat.TSV: partial(self._write_tsv, format_time=gf.time_to_ssmmm),
SyncMapFormat.TSVH: partial(self._write_tsv, format_time=gf.time_to_hhmmssmmm),
Expand Down Expand Up @@ -889,14 +939,14 @@ def _read_smil(self, input_file):
if end is None:
end = gf.time_from_ssmmm(child.get("clipEnd"))
self.append_fragment(
SyncMapFragment(
text_fragment=TextFragment(
identifier=identifier,
lines=[u""] # TODO read text from additional text_file?
),
begin=begin,
end=end
)
SyncMapFragment(
text_fragment=TextFragment(
identifier=identifier,
lines=[u""] # TODO read text from additional text_file?
),
begin=begin,
end=end
)
)

def _write_smil(self, output_file, format_time, parameters):
Expand Down Expand Up @@ -959,14 +1009,14 @@ def _read_srt(self, input_file):
if len(fragment_lines) == 0:
fragment_lines = [u""]
self.append_fragment(
SyncMapFragment(
text_fragment=TextFragment(
identifier=identifier,
lines=fragment_lines
),
begin=begin,
end=end
)
SyncMapFragment(
text_fragment=TextFragment(
identifier=identifier,
lines=fragment_lines
),
begin=begin,
end=end
)
)
i += 1

Expand All @@ -988,6 +1038,71 @@ def _write_srt(self, output_file):
msg.append(u"")
output_file.write(u"\n".join(msg))

def _read_sub(self, input_file, use_newline=False):
""" Read from SUB file """
lines = input_file.readlines()
i = 0
identifier_index = 1
in_subtitle = False
# TODO read [INFORMATION] header?
while i < len(lines):
line = lines[i].strip()
if len(line) > 0:
if (not in_subtitle) and (line == u"[SUBTITLE]"):
in_subtitle = True
if in_subtitle:
timings = line.split(",")
if len(timings) == 2:
identifier = u"f" + str(identifier_index).zfill(6)
identifier_index += 1
begin = gf.time_from_hhmmssmmm(timings[0])
end = gf.time_from_hhmmssmmm(timings[1])
fragment_lines = []
while (i + 1 < len(lines)) and (len(line) > 0):
i += 1
line = lines[i].strip()
if use_newline:
line_split = [l for l in [line] if len(l) > 0]
else:
line_split = [l for l in line.split(u"[br]") if len(l) > 0]
if len(line_split) > 0:
fragment_lines.extend(line_split)
# should never happen, but just in case...
if len(fragment_lines) == 0:
fragment_lines = [u""]
self.append_fragment(
SyncMapFragment(
text_fragment=TextFragment(
identifier=identifier,
lines=fragment_lines
),
begin=begin,
end=end
)
)
i += 1

def _write_sub(self, output_file, use_newline=False):
""" Write to SUB file """
msg = []
# TODO write [INFORMATION] header?
msg.append(u"[SUBTITLE]")
for fragment in self.fragments:
text = fragment.text_fragment
msg.append(u"%s,%s" % (
gf.time_to_hhmmssmmm(fragment.begin),
gf.time_to_hhmmssmmm(fragment.end)
))
if use_newline:
msg.extend(text.lines)
else:
msg.append(u"[br]".join(text.lines))
msg.append(u"")
msg.append(u"[END SUBTITLE]")
# add an extra \n at the end
msg.append(u"")
output_file.write(u"\n".join(msg))

def _read_ssv(self, input_file, parse_time):
""" Read from SSV file """
for line in input_file.readlines():
Expand Down
22 changes: 22 additions & 0 deletions aeneas/tests/res/syncmaps/sonnet001.dfxp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version='1.0' encoding='UTF-8'?>
<tt xmlns="http://www.w3.org/ns/ttml" xml:lang="en">
<body>
<div>
<p xml:id="f000001" begin="0.000s" end="2.680s">1</p>
<p xml:id="f000002" begin="2.680s" end="5.880s">From fairest creatures we desire increase,</p>
<p xml:id="f000003" begin="5.880s" end="9.240s">That thereby beauty's rose might never die,</p>
<p xml:id="f000004" begin="9.240s" end="11.760s">But as the riper should by time decease,</p>
<p xml:id="f000005" begin="11.760s" end="14.440s">His tender heir might bear his memory:</p>
<p xml:id="f000006" begin="14.440s" end="18.560s">But thou contracted to thine own bright eyes,</p>
<p xml:id="f000007" begin="18.560s" end="22.280s">Feed'st thy light's flame with self-substantial fuel,</p>
<p xml:id="f000008" begin="22.280s" end="25.480s">Making a famine where abundance lies,</p>
<p xml:id="f000009" begin="25.480s" end="31.200s">Thy self thy foe, to thy sweet self too cruel:</p>
<p xml:id="f000010" begin="31.200s" end="34.400s">Thou that art now the world's fresh ornament,</p>
<p xml:id="f000011" begin="34.400s" end="36.960s">And only herald to the gaudy spring,</p>
<p xml:id="f000012" begin="36.960s" end="40.640s">Within thine own bud buriest thy content,</p>
<p xml:id="f000013" begin="40.640s" end="43.640s">And tender churl mak'st waste in niggarding:</p>
<p xml:id="f000014" begin="43.640s" end="48.120s">Pity the world, or else this glutton be,</p>
<p xml:id="f000015" begin="48.120s" end="53.240s">To eat the world's due, by the grave and thee.</p>
</div>
</body>
</tt>
47 changes: 47 additions & 0 deletions aeneas/tests/res/syncmaps/sonnet001.sbv
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
[SUBTITLE]
00:00:00.000,00:00:02.680
1

00:00:02.680,00:00:05.879
From fairest creatures we desire increase,

00:00:05.879,00:00:09.240
That thereby beauty's rose might never die,

00:00:09.240,00:00:11.759
But as the riper should by time decease,

00:00:11.759,00:00:14.439
His tender heir might bear his memory:

00:00:14.439,00:00:18.559
But thou contracted to thine own bright eyes,

00:00:18.559,00:00:22.280
Feed'st thy light's flame with self-substantial fuel,

00:00:22.280,00:00:25.480
Making a famine where abundance lies,

00:00:25.480,00:00:31.199
Thy self thy foe, to thy sweet self too cruel:

00:00:31.199,00:00:34.399
Thou that art now the world's fresh ornament,

00:00:34.399,00:00:36.960
And only herald to the gaudy spring,

00:00:36.960,00:00:40.640
Within thine own bud buriest thy content,

00:00:40.640,00:00:43.640
And tender churl mak'st waste in niggarding:

00:00:43.640,00:00:48.119
Pity the world, or else this glutton be,

00:00:48.119,00:00:53.240
To eat the world's due, by the grave and thee.

[END SUBTITLE]
47 changes: 47 additions & 0 deletions aeneas/tests/res/syncmaps/sonnet001.sub
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
[SUBTITLE]
00:00:00.000,00:00:02.680
1

00:00:02.680,00:00:05.879
From fairest creatures we desire increase,

00:00:05.879,00:00:09.240
That thereby beauty's rose might never die,

00:00:09.240,00:00:11.759
But as the riper should by time decease,

00:00:11.759,00:00:14.439
His tender heir might bear his memory:

00:00:14.439,00:00:18.559
But thou contracted to thine own bright eyes,

00:00:18.559,00:00:22.280
Feed'st thy light's flame with self-substantial fuel,

00:00:22.280,00:00:25.480
Making a famine where abundance lies,

00:00:25.480,00:00:31.199
Thy self thy foe, to thy sweet self too cruel:

00:00:31.199,00:00:34.399
Thou that art now the world's fresh ornament,

00:00:34.399,00:00:36.960
And only herald to the gaudy spring,

00:00:36.960,00:00:40.640
Within thine own bud buriest thy content,

00:00:40.640,00:00:43.640
And tender churl mak'st waste in niggarding:

00:00:43.640,00:00:48.119
Pity the world, or else this glutton be,

00:00:48.119,00:00:53.240
To eat the world's due, by the grave and thee.

[END SUBTITLE]
Loading

0 comments on commit 7d6372d

Please sign in to comment.