pycaption 2.2.9__tar.gz → 2.2.11__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. {pycaption-2.2.9/pycaption.egg-info → pycaption-2.2.11}/PKG-INFO +1 -1
  2. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption/base.py +14 -6
  3. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption/scc/__init__.py +19 -13
  4. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption/scc/constants.py +2 -0
  5. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption/scc/specialized_collections.py +9 -3
  6. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption/webvtt.py +10 -2
  7. {pycaption-2.2.9 → pycaption-2.2.11/pycaption.egg-info}/PKG-INFO +1 -1
  8. {pycaption-2.2.9 → pycaption-2.2.11}/setup.py +1 -1
  9. {pycaption-2.2.9 → pycaption-2.2.11}/tests/conftest.py +2 -2
  10. {pycaption-2.2.9 → pycaption-2.2.11}/tests/fixtures/dfxp.py +2 -2
  11. {pycaption-2.2.9 → pycaption-2.2.11}/tests/fixtures/scc.py +40 -0
  12. {pycaption-2.2.9 → pycaption-2.2.11}/tests/test_scc.py +5 -6
  13. {pycaption-2.2.9 → pycaption-2.2.11}/LICENSE +0 -0
  14. {pycaption-2.2.9 → pycaption-2.2.11}/MANIFEST.in +0 -0
  15. {pycaption-2.2.9 → pycaption-2.2.11}/README.rst +0 -0
  16. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption/__init__.py +0 -0
  17. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption/dfxp/__init__.py +0 -0
  18. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption/dfxp/base.py +0 -0
  19. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption/dfxp/extras.py +0 -0
  20. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption/english.pickle +0 -0
  21. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption/exceptions.py +0 -0
  22. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption/geometry.py +0 -0
  23. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption/microdvd.py +0 -0
  24. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption/sami.py +0 -0
  25. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption/scc/state_machines.py +0 -0
  26. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption/scc/translator.py +0 -0
  27. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption/srt.py +0 -0
  28. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption/transcript.py +0 -0
  29. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption/utils.py +0 -0
  30. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption.egg-info/SOURCES.txt +0 -0
  31. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption.egg-info/dependency_links.txt +0 -0
  32. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption.egg-info/requires.txt +0 -0
  33. {pycaption-2.2.9 → pycaption-2.2.11}/pycaption.egg-info/top_level.txt +0 -0
  34. {pycaption-2.2.9 → pycaption-2.2.11}/setup.cfg +0 -0
  35. {pycaption-2.2.9 → pycaption-2.2.11}/tests/__init__.py +0 -0
  36. {pycaption-2.2.9 → pycaption-2.2.11}/tests/fixtures/__init__.py +0 -0
  37. {pycaption-2.2.9 → pycaption-2.2.11}/tests/fixtures/microdvd.py +0 -0
  38. {pycaption-2.2.9 → pycaption-2.2.11}/tests/fixtures/sami.py +0 -0
  39. {pycaption-2.2.9 → pycaption-2.2.11}/tests/fixtures/srt.py +0 -0
  40. {pycaption-2.2.9 → pycaption-2.2.11}/tests/fixtures/translated_scc.py +0 -0
  41. {pycaption-2.2.9 → pycaption-2.2.11}/tests/fixtures/webvtt.py +0 -0
  42. {pycaption-2.2.9 → pycaption-2.2.11}/tests/mixins.py +0 -0
  43. {pycaption-2.2.9 → pycaption-2.2.11}/tests/test_base.py +0 -0
  44. {pycaption-2.2.9 → pycaption-2.2.11}/tests/test_dfxp.py +0 -0
  45. {pycaption-2.2.9 → pycaption-2.2.11}/tests/test_dfxp_conversion.py +0 -0
  46. {pycaption-2.2.9 → pycaption-2.2.11}/tests/test_dfxp_extras.py +0 -0
  47. {pycaption-2.2.9 → pycaption-2.2.11}/tests/test_functions.py +0 -0
  48. {pycaption-2.2.9 → pycaption-2.2.11}/tests/test_geometry.py +0 -0
  49. {pycaption-2.2.9 → pycaption-2.2.11}/tests/test_microdvd.py +0 -0
  50. {pycaption-2.2.9 → pycaption-2.2.11}/tests/test_microdvd_conversion.py +0 -0
  51. {pycaption-2.2.9 → pycaption-2.2.11}/tests/test_sami.py +0 -0
  52. {pycaption-2.2.9 → pycaption-2.2.11}/tests/test_sami_conversion.py +0 -0
  53. {pycaption-2.2.9 → pycaption-2.2.11}/tests/test_scc_conversion.py +0 -0
  54. {pycaption-2.2.9 → pycaption-2.2.11}/tests/test_scc_translator.py +0 -0
  55. {pycaption-2.2.9 → pycaption-2.2.11}/tests/test_srt.py +0 -0
  56. {pycaption-2.2.9 → pycaption-2.2.11}/tests/test_srt_conversion.py +0 -0
  57. {pycaption-2.2.9 → pycaption-2.2.11}/tests/test_webvtt.py +0 -0
  58. {pycaption-2.2.9 → pycaption-2.2.11}/tests/test_webvtt_conversion.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pycaption
3
- Version: 2.2.9
3
+ Version: 2.2.11
4
4
  Summary: Closed caption converter
5
5
  Author: Joe Norton
6
6
  Author-email: joey@nortoncrew.com
@@ -114,13 +114,16 @@ class CaptionNode:
114
114
  STYLE = 2
115
115
  BREAK = 3
116
116
 
117
- def __init__(self, type_, layout_info=None, content=None, start=None):
117
+ def __init__(
118
+ self, type_, layout_info=None, content=None, start=None, position=None
119
+ ):
118
120
  """
119
121
  :type type_: int
120
122
  :type layout_info: Layout
121
123
  """
122
124
  self.type_ = type_
123
125
  self.content = content
126
+ self.position = position
124
127
 
125
128
  # Boolean. Marks the beginning/ end of a Style node.
126
129
  self.start = start
@@ -139,19 +142,24 @@ class CaptionNode:
139
142
  raise RuntimeError(f'Unknown node type: {t}')
140
143
 
141
144
  @staticmethod
142
- def create_text(text, layout_info=None):
145
+ def create_text(text, layout_info=None, position=None):
143
146
  return CaptionNode(
144
- CaptionNode.TEXT, layout_info=layout_info, content=text)
147
+ type_=CaptionNode.TEXT, layout_info=layout_info,
148
+ position=position, content=text
149
+ )
145
150
 
146
151
  @staticmethod
147
152
  def create_style(start, content, layout_info=None):
148
153
  return CaptionNode(
149
- CaptionNode.STYLE, layout_info=layout_info, content=content,
154
+ type_=CaptionNode.STYLE, layout_info=layout_info, content=content,
150
155
  start=start)
151
156
 
152
157
  @staticmethod
153
- def create_break(layout_info=None):
154
- return CaptionNode(CaptionNode.BREAK, layout_info=layout_info)
158
+ def create_break(layout_info=None, content=None):
159
+ return CaptionNode(
160
+ type_=CaptionNode.BREAK, layout_info=layout_info,
161
+ content=content
162
+ )
155
163
 
156
164
 
157
165
  class Caption:
@@ -94,7 +94,7 @@ from .constants import (
94
94
  MICROSECONDS_PER_CODEWORD, CHARACTER_TO_CODE,
95
95
  SPECIAL_OR_EXTENDED_CHAR_TO_CODE, PAC_BYTES_TO_POSITIONING_MAP,
96
96
  PAC_HIGH_BYTE_BY_ROW, PAC_LOW_BYTE_BY_ROW_RESTRICTED,
97
- PAC_TAB_OFFSET_COMMANDS,
97
+ PAC_TAB_OFFSET_COMMANDS, CUE_STARTING_COMMAND
98
98
  )
99
99
  from .specialized_collections import ( # noqa: F401
100
100
  TimingCorrectingCaptionList, NotifyingDict, CaptionCreator,
@@ -164,6 +164,7 @@ class SCCReader(BaseReader):
164
164
  )
165
165
 
166
166
  self.last_command = ''
167
+ self.double_starter = False
167
168
 
168
169
  self.buffer_dict = NotifyingDict()
169
170
 
@@ -223,6 +224,7 @@ class SCCReader(BaseReader):
223
224
  # split lines
224
225
  lines = content.splitlines()
225
226
 
227
+
226
228
  # loop through each line except the first
227
229
  for line in lines[1:]:
228
230
  self._translate_line(line)
@@ -307,24 +309,21 @@ class SCCReader(BaseReader):
307
309
  parts = r.findall(line.lower())
308
310
 
309
311
  self.time_translator.start_at(parts[0][0])
310
-
311
312
  word_list = parts[0][2].split(' ')
312
- pacs_are_doubled = len(word_list) > 1 and word_list[0] == word_list[1]
313
+
313
314
  for idx, word in enumerate(word_list):
314
- # ignore empty results or invalid commands
315
315
  word = word.strip()
316
- previous_is_pac_or_tab = idx > 0 and (
317
- _is_pac_command(word_list[idx-1]) or word_list[idx-1] in PAC_TAB_OFFSET_COMMANDS
316
+ previous_is_pac_or_tab = len(word_list) > 1 and (
317
+ _is_pac_command(word_list[idx - 1]) or word_list[idx - 1] in PAC_TAB_OFFSET_COMMANDS
318
318
  )
319
319
  if len(word) == 4:
320
320
  self._translate_word(
321
321
  word=word,
322
322
  previous_is_pac_or_tab=previous_is_pac_or_tab,
323
- pacs_are_doubled=pacs_are_doubled
324
323
  )
325
324
 
326
- def _translate_word(self, word, previous_is_pac_or_tab, pacs_are_doubled):
327
- if self._handle_double_command(word, pacs_are_doubled):
325
+ def _translate_word(self, word, previous_is_pac_or_tab):
326
+ if self._handle_double_command(word):
328
327
  # count frames for timing
329
328
  self.time_translator.increment_frames()
330
329
  return
@@ -348,7 +347,7 @@ class SCCReader(BaseReader):
348
347
  # count frames for timing only after processing a command
349
348
  self.time_translator.increment_frames()
350
349
 
351
- def _handle_double_command(self, word, pacs_are_doubled):
350
+ def _handle_double_command(self, word):
352
351
  # If the caption is to be broadcast, each of the commands are doubled
353
352
  # up for redundancy in case the signal is garbled in transmission.
354
353
  # The decoder is programmed to ignore a second command when it is the
@@ -356,11 +355,18 @@ class SCCReader(BaseReader):
356
355
  # If we have doubled commands we're skipping also
357
356
  # doubled special characters and doubled extended characters
358
357
  # with only one member of each pair being displayed.
359
- doubled_types = word in COMMANDS or _is_pac_command(word)
360
- if pacs_are_doubled:
361
- doubled_types = doubled_types or word in SPECIAL_CHARS or word in EXTENDED_CHARS
358
+
359
+ doubled_types = word != "94a1" and word in COMMANDS or _is_pac_command(word)
360
+ if self.double_starter:
361
+ doubled_types = doubled_types or word in EXTENDED_CHARS or word == "94a1" or word in SPECIAL_CHARS
362
+
363
+ if word in CUE_STARTING_COMMAND and word != self.last_command:
364
+ self.double_starter = False
362
365
 
363
366
  if doubled_types and word == self.last_command:
367
+ if word in CUE_STARTING_COMMAND:
368
+ self.double_starter = True
369
+ self.last_command = ''
364
370
  return True
365
371
  # Fix for the <position> <tab offset> <position> <tab offset>
366
372
  # repetition
@@ -1058,3 +1058,5 @@ BACKGROUND_COLOR_CODES = [
1058
1058
  "10a7", "10a8", "1029", "102a", "10ab", "102c", "10ad",
1059
1059
  "10ae", "102f", "97ad"
1060
1060
  ]
1061
+
1062
+ CUE_STARTING_COMMAND = ['9425', '9426', '94a7', '9429', '9420']
@@ -1,5 +1,4 @@
1
1
  import collections
2
- import unicodedata
3
2
 
4
3
  from ..base import CaptionList, Caption, CaptionNode
5
4
  from ..geometry import (
@@ -9,7 +8,7 @@ from ..geometry import (
9
8
  from .constants import (
10
9
  PAC_BYTES_TO_POSITIONING_MAP, COMMANDS, PAC_TAB_OFFSET_COMMANDS,
11
10
  MICROSECONDS_PER_CODEWORD, BACKGROUND_COLOR_CODES,
12
- MID_ROW_CODES, EXTENDED_CHARS, SPECIAL_CHARS
11
+ MID_ROW_CODES, EXTENDED_CHARS
13
12
  )
14
13
 
15
14
  PopOnCue = collections.namedtuple("PopOnCue", "buffer, start, end")
@@ -255,7 +254,10 @@ class CaptionCreator:
255
254
  layout_info = _get_layout_from_tuple(instruction.position)
256
255
  caption.nodes.append(
257
256
  CaptionNode.create_text(
258
- instruction.text, layout_info=layout_info),
257
+ text=instruction.text,
258
+ layout_info=layout_info,
259
+ position=instruction.position
260
+ )
259
261
  )
260
262
  caption.layout_info = layout_info
261
263
 
@@ -366,6 +368,10 @@ class InstructionNodeCreator:
366
368
  self._collection[-1].text = self._collection[-1].text[:-1]
367
369
 
368
370
  if 'italic' in text:
371
+ if self._position_tracer.is_linebreak_required():
372
+ self._collection.append(_InstructionNode.create_break(
373
+ position=self._position_tracer.get_current_position()))
374
+ self._position_tracer.acknowledge_linebreak_consumed()
369
375
  if 'end' not in text:
370
376
  self._collection.append(
371
377
  _InstructionNode.create_italics_style(
@@ -394,6 +394,7 @@ class WebVTTWriter(BaseWriter):
394
394
  return []
395
395
 
396
396
  current_layout = None
397
+ current_node = None
397
398
 
398
399
  # A list with layout groups. Since WebVTT only support positioning
399
400
  # for different cues, each layout group has to be represented in a
@@ -402,17 +403,24 @@ class WebVTTWriter(BaseWriter):
402
403
  # A properly encoded WebVTT string (plain unicode must be properly
403
404
  # escaped before being appended to this string)
404
405
  s = ''
406
+ row, column, prev_row, prev_column = 0, 0, 0, 0
405
407
  for i, node in enumerate(nodes):
406
408
  if node.type_ == CaptionNode.TEXT:
407
409
  if s and current_layout and node.layout_info != current_layout:
408
410
  # If the positioning changes from one text node to
409
411
  # another, a new WebVTT cue has to be created.
410
- layout_groups.append((s, current_layout))
411
- s = ''
412
+ row, column = node.position if node.position else (0, 0)
413
+ prev_row, prev_column = current_node.position if current_node.position else (0, 0)
414
+ if row == prev_row + 1:
415
+ s += '\n'
416
+ else:
417
+ layout_groups.append((s, current_layout))
418
+ s = ''
412
419
  # ATTENTION: This is where the plain unicode node content is
413
420
  # finally encoded as WebVTT.
414
421
  s += self._encode_illegal_characters(node.content) or '&nbsp;'
415
422
  current_layout = node.layout_info
423
+ current_node = node
416
424
  elif node.type_ == CaptionNode.STYLE:
417
425
  resulting_style = self._calculate_resulting_style(
418
426
  node.content, caption_set
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pycaption
3
- Version: 2.2.9
3
+ Version: 2.2.11
4
4
  Summary: Closed caption converter
5
5
  Author: Joe Norton
6
6
  Author-email: joey@nortoncrew.com
@@ -24,7 +24,7 @@ transcript_dependencies = [
24
24
 
25
25
  setup(
26
26
  name='pycaption',
27
- version='2.2.9',
27
+ version='2.2.11',
28
28
  description='Closed caption converter',
29
29
  long_description=open(README_PATH).read(),
30
30
  author='Joe Norton',
@@ -54,14 +54,14 @@ from tests.fixtures.scc import ( # noqa: F401
54
54
  scc_that_generates_webvtt_with_proper_newlines,
55
55
  sample_scc_produces_captions_with_start_and_end_time_the_same,
56
56
  sample_scc_pop_on, sample_scc_multiple_positioning, sample_scc_with_italics,
57
- sample_scc_empty, sample_scc_roll_up_ru2, sample_no_positioning_at_all_scc,
57
+ sample_scc_empty, sample_scc_roll_up_ru2, sample_scc_roll_up_ru3,
58
+ sample_no_positioning_at_all_scc, sample_scc_with_line_too_long,
58
59
  sample_scc_no_explicit_end_to_last_caption, sample_scc_flashing_cue,
59
60
  sample_scc_eoc_first_command, sample_scc_with_extended_characters,
60
61
  sample_scc_with_ampersand_character, sample_scc_multiple_formats,
61
62
  sample_scc_duplicate_tab_offset, sample_scc_duplicate_special_characters,
62
63
  sample_scc_tab_offset, sample_scc_with_unknown_commands,
63
64
  sample_scc_special_and_extended_characters,
64
- sample_scc_with_line_too_long
65
65
  )
66
66
  from tests.fixtures.srt import ( # noqa: F401
67
67
  sample_srt, sample_srt_ascii, sample_srt_numeric, sample_srt_empty,
@@ -920,10 +920,10 @@ def sample_dfxp_from_scc_output():
920
920
  <region tts:displayAlign="before" tts:origin="40% 53%" tts:textAlign="left" xml:id="r5"/>
921
921
  <region tts:displayAlign="before" tts:origin="70% 17%" tts:textAlign="left" xml:id="r6"/>
922
922
  <region tts:displayAlign="before" tts:origin="20% 35%" tts:textAlign="left" xml:id="r7"/>
923
- <region tts:displayAlign="before" tts:origin="25% 83%" tts:textAlign="left" xml:id="r8"/>
923
+ <region tts:displayAlign="before" tts:origin="20% 83%" tts:textAlign="left" xml:id="r8"/>
924
924
  <region tts:displayAlign="before" tts:origin="70% 11%" tts:textAlign="left" xml:id="r9"/>
925
925
  <region tts:displayAlign="before" tts:origin="40% 41%" tts:textAlign="left" xml:id="r10"/>
926
- <region tts:displayAlign="before" tts:origin="25% 71%" tts:textAlign="left" xml:id="r11"/>
926
+ <region tts:displayAlign="before" tts:origin="20% 71%" tts:textAlign="left" xml:id="r11"/>
927
927
  </layout>
928
928
  </head>
929
929
  <body>
@@ -140,6 +140,46 @@ Scenarist_SCC V1.0
140
140
 
141
141
  00:00:12;07 9425 9425 94ad 94ad 9470 9470 91b0 9131 9132 9132
142
142
 
143
+ 00:00:12;30 9425 94ad 94ad 9470 9470 91b0 9131 9132 9132
144
+
145
+ 00:00:13;07 9425 9425 94ad 94ad 9470 9470 c1c2 c3c4 c580 91bf
146
+
147
+ 00:00:14;07 9425 9425 94ad 94ad 9470 9470 9220 9220 92a1 92a2 92a7
148
+
149
+ 00:00:17;01 9426 9426 94ad 94ad 9470 9470 57c8 4552 4520 d94f d5a7 5245 20d3 54c1 cec4 49ce c720 ce4f 572c
150
+
151
+ 00:00:18;19 9426 9426 94ad 94ad 9470 9470 4c4f 4fcb 49ce c720 4fd5 5420 54c8 4552 452c 2054 c8c1 54a7 d320 c14c 4c
152
+
153
+ 00:00:20;06 9426 9426 94ad 94ad 9470 9470 54c8 4520 4352 4f57 c4ae
154
+
155
+ 00:00:21;24 9426 9426 94ad 94ad 9470 9470 3e3e 2049 5420 57c1 d320 c74f 4fc4 2054 4f20 c245 2049 ce20 54c8 45
156
+
157
+ 00:00:34;27 94a7 94ad 9470 c16e 6420 f2e5 73f4 eff2 e520 49ef f761 a773 20ec 616e 642c 20f7 61f4 e5f2
158
+
159
+ 00:00:36;12 94a7 94ad 9470 c16e 6420 f7e9 ec64 ece9 e6e5 ae80
160
+
161
+ 00:00:44;08 94a7 94ad 9470 3e3e 20c2 e96b e520 49ef f761 2c20 79ef 75f2 2073 ef75 f2e3 e520 e6ef f280
162
+ """
163
+
164
+
165
+ @pytest.fixture(scope="session")
166
+ def sample_scc_roll_up_ru3():
167
+ return """\
168
+ Scenarist_SCC V1.0
169
+ 00:00:00;22 9425 9425 94ad 94ad 9470 9470 3e3e 3e20 c849 ae80
170
+
171
+ 00:00:02;23 9425 9425 94ad 94ad 9470 9470 49a7 cd20 cb45 d649 ce20 43d5 cece 49ce c720 c1ce c420 c154
172
+
173
+ 00:00:04;17 9425 9425 94ad 94ad 9470 9470 49ce d645 d354 4f52 a7d3 20c2 c1ce cb20 5745 20c2 454c 4945 d645 2049 ce80
174
+
175
+ 00:00:06;04 9425 9425 94ad 94ad 9470 9470 c845 4cd0 49ce c720 54c8 4520 4c4f 43c1 4c20 ce45 49c7 c8c2 4f52 c84f 4fc4 d380
176
+
177
+ 00:00:09;21 9425 9425 94ad 94ad 9470 9470 c1ce c420 49cd d052 4fd6 49ce c720 54c8 4520 4c49 d645 d320 4f46 20c1 4c4c
178
+
179
+ 00:00:11;07 9425 9425 94ad 94ad 9470 9470 5745 20d3 4552 d645 ae80
180
+
181
+ 00:00:12;07 9425 9425 94ad 94ad 9470 9470 91b0 9131 9132 9132
182
+
143
183
  00:00:13;07 9425 9425 94ad 94ad 9470 9470 c1c2 c3c4 c580 91bf
144
184
 
145
185
  00:00:14;07 9425 9425 94ad 94ad 9470 9470 9220 9220 92a1 92a2 92a7
@@ -77,10 +77,10 @@ class TestSCCReader(ReaderTestingMixIn):
77
77
  ((40.0, UnitEnum.PERCENT), (53.0, UnitEnum.PERCENT)),
78
78
  ((70.0, UnitEnum.PERCENT), (17.0, UnitEnum.PERCENT)),
79
79
  ((20.0, UnitEnum.PERCENT), (35.0, UnitEnum.PERCENT)),
80
- ((25.0, UnitEnum.PERCENT), (83.0, UnitEnum.PERCENT)),
80
+ ((20.0, UnitEnum.PERCENT), (83.0, UnitEnum.PERCENT)),
81
81
  ((70.0, UnitEnum.PERCENT), (11.0, UnitEnum.PERCENT)),
82
82
  ((40.0, UnitEnum.PERCENT), (41.0, UnitEnum.PERCENT)),
83
- ((25.0, UnitEnum.PERCENT), (71.0, UnitEnum.PERCENT))
83
+ ((20.0, UnitEnum.PERCENT), (71.0, UnitEnum.PERCENT))
84
84
  ]
85
85
  actual_positioning = [
86
86
  caption_.layout_info.origin.serialized()
@@ -227,7 +227,6 @@ class TestSCCReader(ReaderTestingMixIn):
227
227
  '®°½¿™¢£♪à èâêîôû',
228
228
  '®°AA½¿™¢£♪à èâêAAîôû'
229
229
  ]
230
-
231
230
  caption_set = SCCReader().read(sample_scc_duplicate_special_characters)
232
231
  actual_lines = [
233
232
  node.content
@@ -279,6 +278,7 @@ class TestCoverageOnly:
279
278
  'AND IMPROVING THE LIVES OF ALL',
280
279
  'WE SERVE.',
281
280
  '®°½',
281
+ '®°½½',
282
282
  'ABû',
283
283
  'ÁÉÓ¡',
284
284
  "WHERE YOU'RE STANDING NOW,",
@@ -323,8 +323,8 @@ class TestCoverageOnly:
323
323
 
324
324
  assert expected_text_lines == text_lines
325
325
 
326
- def test_freeze_semicolon_spec_time(self, sample_scc_roll_up_ru2):
327
- scc1 = SCCReader().read(sample_scc_roll_up_ru2)
326
+ def test_freeze_semicolon_spec_time(self, sample_scc_roll_up_ru3):
327
+ scc1 = SCCReader().read(sample_scc_roll_up_ru3)
328
328
  captions = scc1.get_captions('en-US')
329
329
  expected_timings = [
330
330
  (733333.3333333333, 2766666.6666666665),
@@ -346,7 +346,6 @@ class TestCoverageOnly:
346
346
  ]
347
347
 
348
348
  actual_timings = [(c_.start, c_.end) for c_ in captions]
349
-
350
349
  assert expected_timings == actual_timings
351
350
 
352
351
  def test_freeze_colon_spec_time(self, sample_scc_pop_on):
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes