TonieToolbox 0.5.0a1__py3-none-any.whl → 0.6.0a1__py3-none-any.whl

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.
@@ -15,18 +15,17 @@ from .ogg_page import OggPage
15
15
  from .constants import OPUS_TAGS, SAMPLE_RATE_KHZ, TIMESTAMP_DEDUCT
16
16
  from .logger import get_logger
17
17
 
18
- # Setup logging
19
18
  logger = get_logger('tonie_file')
20
19
 
21
20
 
22
- def toniefile_comment_add(buffer, length, comment_str):
21
+ def toniefile_comment_add(buffer: bytearray, length: int, comment_str: str) -> int:
23
22
  """
24
23
  Add a comment string to an Opus comment packet buffer.
25
24
 
26
25
  Args:
27
- buffer: Bytearray buffer to add comment to
28
- length: Current position in the buffer
29
- comment_str: Comment string to add
26
+ buffer (bytearray): Bytearray buffer to add comment to
27
+ length (int): Current position in the buffer
28
+ comment_str (str): Comment string to add
30
29
 
31
30
  Returns:
32
31
  int: New position in the buffer after adding comment
@@ -38,7 +37,6 @@ def toniefile_comment_add(buffer, length, comment_str):
38
37
  buffer[length:length+4] = struct.pack("<I", str_length)
39
38
  length += 4
40
39
 
41
- # Add the actual string
42
40
  buffer[length:length+str_length] = comment_str.encode('utf-8')
43
41
  length += str_length
44
42
 
@@ -46,7 +44,7 @@ def toniefile_comment_add(buffer, length, comment_str):
46
44
  return length
47
45
 
48
46
 
49
- def check_identification_header(page):
47
+ def check_identification_header(page) -> None:
50
48
  """
51
49
  Check if a page contains a valid Opus identification header.
52
50
 
@@ -79,16 +77,16 @@ def check_identification_header(page):
79
77
  logger.debug("Opus identification header is valid")
80
78
 
81
79
 
82
- def prepare_opus_tags(page, custom_tags=False, bitrate=64, vbr=True, opus_binary=None):
80
+ def prepare_opus_tags(page, custom_tags: bool = False, bitrate: int = 64, vbr: bool = True, opus_binary: str = None) -> OggPage:
83
81
  """
84
82
  Prepare standard Opus tags for a Tonie file.
85
83
 
86
84
  Args:
87
85
  page: OggPage to modify
88
- custom_tags: Whether to use custom TonieToolbox tags instead of default ones
89
- bitrate: Actual bitrate used for encoding
90
- vbr: Whether variable bitrate was used
91
- opus_binary: Path to opusenc binary for version detection
86
+ custom_tags (bool): Whether to use custom TonieToolbox tags instead of default ones
87
+ bitrate (int): Actual bitrate used for encoding
88
+ vbr (bool): Whether variable bitrate was used
89
+ opus_binary (str | None): Path to opusenc binary for version detection
92
90
 
93
91
  Returns:
94
92
  OggPage: Modified page with Tonie-compatible Opus tags
@@ -115,49 +113,38 @@ def prepare_opus_tags(page, custom_tags=False, bitrate=64, vbr=True, opus_binary
115
113
  # Use custom tags for TonieToolbox
116
114
  # Create buffer for opus tags (similar to teddyCloud implementation)
117
115
  logger.debug("Creating custom Opus tags")
118
- comment_data = bytearray(0x1B4) # Same size as in teddyCloud
119
-
120
- # OpusTags signature
116
+ comment_data = bytearray(0x1B4)
121
117
  comment_data_pos = 0
122
118
  comment_data[comment_data_pos:comment_data_pos+8] = b"OpusTags"
123
- comment_data_pos += 8
124
-
119
+ comment_data_pos += 8
125
120
  # Vendor string
126
- comment_data_pos = toniefile_comment_add(comment_data, comment_data_pos, "TonieToolbox")
127
-
121
+ comment_data_pos = toniefile_comment_add(comment_data, comment_data_pos, "TonieToolbox")
128
122
  # Number of comments (3 comments: version, encoder info, and encoder options)
129
123
  comments_count = 3
130
124
  comment_data[comment_data_pos:comment_data_pos+4] = struct.pack("<I", comments_count)
131
- comment_data_pos += 4
132
-
125
+ comment_data_pos += 4
133
126
  # Add version information
134
127
  from . import __version__
135
128
  version_str = f"version={__version__}"
136
- comment_data_pos = toniefile_comment_add(comment_data, comment_data_pos, version_str)
137
-
129
+ comment_data_pos = toniefile_comment_add(comment_data, comment_data_pos, version_str)
138
130
  # Get actual opusenc version
139
131
  from .dependency_manager import get_opus_version
140
132
  encoder_info = get_opus_version(opus_binary)
141
- comment_data_pos = toniefile_comment_add(comment_data, comment_data_pos, f"encoder={encoder_info}")
142
-
133
+ comment_data_pos = toniefile_comment_add(comment_data, comment_data_pos, f"encoder={encoder_info}")
143
134
  # Create encoder options string with actual settings
144
135
  vbr_opt = "--vbr" if vbr else "--cbr"
145
136
  encoder_options = f"encoder_options=--bitrate {bitrate} {vbr_opt}"
146
- comment_data_pos = toniefile_comment_add(comment_data, comment_data_pos, encoder_options)
147
-
137
+ comment_data_pos = toniefile_comment_add(comment_data, comment_data_pos, encoder_options)
148
138
  # Add padding
149
139
  remain = len(comment_data) - comment_data_pos - 4
150
140
  comment_data[comment_data_pos:comment_data_pos+4] = struct.pack("<I", remain)
151
141
  comment_data_pos += 4
152
- comment_data[comment_data_pos:comment_data_pos+4] = b"pad="
153
-
142
+ comment_data[comment_data_pos:comment_data_pos+4] = b"pad="
154
143
  # Create segments - handle data in chunks of 255 bytes maximum
155
- comment_data = comment_data[:comment_data_pos + remain] # Trim to actual used size
156
-
144
+ comment_data = comment_data[:comment_data_pos + remain] # Trim to actual used size
157
145
  # Split large data into smaller segments (each <= 255 bytes)
158
146
  remaining_data = comment_data
159
- first_segment = True
160
-
147
+ first_segment = True
161
148
  while remaining_data:
162
149
  chunk_size = min(255, len(remaining_data))
163
150
  segment = OpusPacket(None)
@@ -175,19 +162,28 @@ def prepare_opus_tags(page, custom_tags=False, bitrate=64, vbr=True, opus_binary
175
162
  return page
176
163
 
177
164
 
178
- def copy_first_and_second_page(in_file, out_file, timestamp, sha, use_custom_tags=True, bitrate=64, vbr=True, opus_binary=None):
165
+ def copy_first_and_second_page(
166
+ in_file,
167
+ out_file,
168
+ timestamp: int,
169
+ sha,
170
+ use_custom_tags: bool = True,
171
+ bitrate: int = 64,
172
+ vbr: bool = True,
173
+ opus_binary: str = None
174
+ ) -> None:
179
175
  """
180
176
  Copy and modify the first two pages of an Opus file for a Tonie file.
181
177
 
182
178
  Args:
183
179
  in_file: Input file handle
184
180
  out_file: Output file handle
185
- timestamp: Timestamp to use for the Tonie file
181
+ timestamp (int): Timestamp to use for the Tonie file
186
182
  sha: SHA1 hash object to update with written data
187
- use_custom_tags: Whether to use custom TonieToolbox tags
188
- bitrate: Actual bitrate used for encoding
189
- vbr: Whether VBR was used
190
- opus_binary: Path to opusenc binary
183
+ use_custom_tags (bool): Whether to use custom TonieToolbox tags
184
+ bitrate (int): Actual bitrate used for encoding
185
+ vbr (bool): Whether VBR was used
186
+ opus_binary (str | None): Path to opusenc binary
191
187
  """
192
188
  logger.debug("Copying first and second pages with timestamp %d", timestamp)
193
189
  found = OggPage.seek_to_page_header(in_file)
@@ -215,7 +211,7 @@ def copy_first_and_second_page(in_file, out_file, timestamp, sha, use_custom_tag
215
211
  logger.debug("Second page written successfully")
216
212
 
217
213
 
218
- def skip_first_two_pages(in_file):
214
+ def skip_first_two_pages(in_file) -> None:
219
215
  """
220
216
  Skip the first two pages of an Opus file.
221
217
 
@@ -248,7 +244,7 @@ def skip_first_two_pages(in_file):
248
244
  logger.debug("First two pages skipped successfully")
249
245
 
250
246
 
251
- def read_all_remaining_pages(in_file):
247
+ def read_all_remaining_pages(in_file) -> list:
252
248
  """
253
249
  Read all remaining OGG pages from an input file.
254
250
 
@@ -273,19 +269,26 @@ def read_all_remaining_pages(in_file):
273
269
  return remaining_pages
274
270
 
275
271
 
276
- def resize_pages(old_pages, max_page_size, first_page_size, template_page, last_granule=0, start_no=2,
277
- set_last_page_flag=False):
272
+ def resize_pages(
273
+ old_pages: list,
274
+ max_page_size: int,
275
+ first_page_size: int,
276
+ template_page,
277
+ last_granule: int = 0,
278
+ start_no: int = 2,
279
+ set_last_page_flag: bool = False
280
+ ) -> list:
278
281
  """
279
282
  Resize OGG pages to fit Tonie requirements.
280
283
 
281
284
  Args:
282
- old_pages: List of original OggPage objects
283
- max_page_size: Maximum size for pages
284
- first_page_size: Size for the first page
285
+ old_pages (list): List of original OggPage objects
286
+ max_page_size (int): Maximum size for pages
287
+ first_page_size (int): Size for the first page
285
288
  template_page: Template OggPage to use for creating new pages
286
- last_granule: Last granule position
287
- start_no: Starting page number
288
- set_last_page_flag: Whether to set the last page flag
289
+ last_granule (int): Last granule position
290
+ start_no (int): Starting page number
291
+ set_last_page_flag (bool): Whether to set the last page flag
289
292
 
290
293
  Returns:
291
294
  list: List of resized OggPage objects
@@ -339,14 +342,14 @@ def resize_pages(old_pages, max_page_size, first_page_size, template_page, last_
339
342
  return new_pages
340
343
 
341
344
 
342
- def fix_tonie_header(out_file, chapters, timestamp, sha):
345
+ def fix_tonie_header(out_file, chapters: list, timestamp: int, sha) -> None:
343
346
  """
344
347
  Fix the Tonie header in a file.
345
348
 
346
349
  Args:
347
350
  out_file: Output file handle
348
- chapters: List of chapter page numbers
349
- timestamp: Timestamp for the Tonie file
351
+ chapters (list): List of chapter page numbers
352
+ timestamp (int): Timestamp for the Tonie file
350
353
  sha: SHA1 hash object with file content
351
354
  """
352
355
  logger.info("Writing Tonie header with %d chapters and timestamp %d", len(chapters), timestamp)
@@ -375,31 +378,43 @@ def fix_tonie_header(out_file, chapters, timestamp, sha):
375
378
  logger.debug("Tonie header written successfully (size: %d bytes)", len(header))
376
379
 
377
380
 
378
- def create_tonie_file(output_file, input_files, no_tonie_header=False, user_timestamp=None,
379
- bitrate=96, vbr=True, ffmpeg_binary=None, opus_binary=None, keep_temp=False, auto_download=False,
380
- use_custom_tags=True):
381
+ def create_tonie_file(
382
+ output_file: str,
383
+ input_files: list[str],
384
+ no_tonie_header: bool = False,
385
+ user_timestamp: str = None,
386
+ bitrate: int = 96,
387
+ vbr: bool = True,
388
+ ffmpeg_binary: str = None,
389
+ opus_binary: str = None,
390
+ keep_temp: bool = False,
391
+ auto_download: bool = False,
392
+ use_custom_tags: bool = True,
393
+ no_mono_conversion: bool = False
394
+ ) -> None:
381
395
  """
382
396
  Create a Tonie file from input files.
383
397
 
384
398
  Args:
385
- output_file: Output file path
386
- input_files: List of input file paths
387
- no_tonie_header: Whether to omit the Tonie header
388
- user_timestamp: Custom timestamp to use
389
- bitrate: Bitrate for encoding in kbps
390
- vbr: Whether to use variable bitrate encoding (True) or constant (False)
391
- ffmpeg_binary: Path to ffmpeg binary
392
- opus_binary: Path to opusenc binary
393
- keep_temp: Whether to keep temporary opus files for testing
394
- auto_download: Whether to automatically download dependencies if not found
395
- use_custom_tags: Whether to use dynamic comment tags generated with toniefile_comment_add
399
+ output_file (str): Output file path
400
+ input_files (list[str]): List of input file paths
401
+ no_tonie_header (bool): Whether to omit the Tonie header
402
+ user_timestamp (str | None): Custom timestamp to use
403
+ bitrate (int): Bitrate for encoding in kbps
404
+ vbr (bool): Whether to use variable bitrate encoding (True) or constant (False)
405
+ ffmpeg_binary (str | None): Path to ffmpeg binary
406
+ opus_binary (str | None): Path to opusenc binary
407
+ keep_temp (bool): Whether to keep temporary opus files for testing
408
+ auto_download (bool): Whether to automatically download dependencies if not found
409
+ use_custom_tags (bool): Whether to use dynamic comment tags generated with toniefile_comment_add
410
+ no_mono_conversion (bool): Whether to skip mono conversion during audio processing
396
411
  """
397
412
  from .audio_conversion import get_opus_tempfile
398
413
 
399
414
  logger.trace("Entering create_tonie_file(output_file=%s, input_files=%s, no_tonie_header=%s, user_timestamp=%s, "
400
- "bitrate=%d, vbr=%s, ffmpeg_binary=%s, opus_binary=%s, keep_temp=%s, auto_download=%s, use_custom_tags=%s)",
415
+ "bitrate=%d, vbr=%s, ffmpeg_binary=%s, opus_binary=%s, keep_temp=%s, auto_download=%s, use_custom_tags=%s, no_mono_conversion=%s)",
401
416
  output_file, input_files, no_tonie_header, user_timestamp, bitrate, vbr, ffmpeg_binary,
402
- opus_binary, keep_temp, auto_download, use_custom_tags)
417
+ opus_binary, keep_temp, auto_download, use_custom_tags, no_mono_conversion)
403
418
 
404
419
  logger.info("Creating Tonie file from %d input files", len(input_files))
405
420
  logger.debug("Output file: %s, Bitrate: %d kbps, VBR: %s, No header: %s",
@@ -465,9 +480,9 @@ def create_tonie_file(output_file, input_files, no_tonie_header=False, user_time
465
480
  handle = open(fname, "rb")
466
481
  temp_file_path = None
467
482
  else:
468
- logger.debug("Converting %s to Opus format (bitrate: %d kbps, VBR: %s)",
469
- fname, bitrate, vbr)
470
- handle, temp_file_path = get_opus_tempfile(ffmpeg_binary, opus_binary, fname, bitrate, vbr, keep_temp, auto_download)
483
+ logger.debug("Converting %s to Opus format (bitrate: %d kbps, VBR: %s, no_mono_conversion: %s)",
484
+ fname, bitrate, vbr, no_mono_conversion)
485
+ handle, temp_file_path = get_opus_tempfile(ffmpeg_binary, opus_binary, fname, bitrate, vbr, keep_temp, auto_download, no_mono_conversion=no_mono_conversion)
471
486
  if temp_file_path:
472
487
  temp_files.append(temp_file_path)
473
488
  logger.debug("Temporary opus file saved to: %s", temp_file_path)