mirror of
https://github.com/iluvcapra/ptulsconv.git
synced 2026-10-01 17:27:27 +00:00
ruffage
This commit is contained in:
@@ -42,6 +42,11 @@ doc = [
|
|||||||
"sphinx-rtd-theme>=3.0.2",
|
"sphinx-rtd-theme>=3.0.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
ignore = [
|
||||||
|
"DTZ005" # datetime created without a tz
|
||||||
|
]
|
||||||
|
|
||||||
[tool.ruff.lint.per-file-ignores]
|
[tool.ruff.lint.per-file-ignores]
|
||||||
"reaper/Export Items as Text.py" = ["F821"]
|
"reaper/Export Items as Text.py" = ["F821"]
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#
|
#
|
||||||
import datetime
|
import datetime
|
||||||
import json
|
import json
|
||||||
import time
|
from zoneinfo import ZoneInfo
|
||||||
|
|
||||||
item_records = []
|
item_records = []
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ output["project_frame_rate"], _, output["project_drop_frame"] = (
|
|||||||
|
|
||||||
output_path, _ = RPR_GetProjectPath("", 1024)
|
output_path, _ = RPR_GetProjectPath("", 1024)
|
||||||
|
|
||||||
now = datetime.datetime.now(tz=time.tzname)
|
now = datetime.datetime.now()
|
||||||
output_title = output["project_title"]
|
output_title = output["project_title"]
|
||||||
|
|
||||||
if output_title == "":
|
if output_title == "":
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ def main():
|
|||||||
(options, args) = parser.parse_args(sys.argv)
|
(options, args) = parser.parse_args(sys.argv)
|
||||||
|
|
||||||
print_section_header_style("Startup")
|
print_section_header_style("Startup")
|
||||||
print_status_style("This run started %s" % (datetime.datetime.now().isoformat()))
|
print_status_style(f"This run started {datetime.datetime.now().isoformat()}")
|
||||||
|
|
||||||
if options.show_tags:
|
if options.show_tags:
|
||||||
dump_field_map()
|
dump_field_map()
|
||||||
@@ -124,17 +124,6 @@ def main():
|
|||||||
input_file=args[1], major_mode=major_mode, warnings=options.warnings
|
input_file=args[1], major_mode=major_mode, warnings=options.warnings
|
||||||
)
|
)
|
||||||
|
|
||||||
except FileNotFoundError as e:
|
|
||||||
print_fatal_error("Error trying to read input file")
|
|
||||||
raise e
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
import traceback
|
|
||||||
|
|
||||||
print_fatal_error("Error trying to convert file")
|
|
||||||
print("\033[31m" + e.__repr__() + "\033[0m", file=sys.stderr)
|
|
||||||
print(traceback.format_exc())
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -2,11 +2,13 @@
|
|||||||
Useful functions for parsing and working with timecode.
|
Useful functions for parsing and working with timecode.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import math
|
import math
|
||||||
import re
|
import re
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
from typing import Optional, SupportsFloat
|
from typing import SupportsFloat
|
||||||
|
|
||||||
|
|
||||||
class TimecodeFormat(
|
class TimecodeFormat(
|
||||||
@@ -16,7 +18,7 @@ class TimecodeFormat(
|
|||||||
A struct reperesenting a timecode datum.
|
A struct reperesenting a timecode datum.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def smpte_to_seconds(self, smpte: str) -> Optional[Fraction]:
|
def smpte_to_seconds(self, smpte: str) -> Fraction | None:
|
||||||
frame_count = smpte_to_frame_count(
|
frame_count = smpte_to_frame_count(
|
||||||
smpte, self.logical_fps, drop_frame_hint=self.drop_frame
|
smpte, self.logical_fps, drop_frame_hint=self.drop_frame
|
||||||
)
|
)
|
||||||
@@ -32,7 +34,7 @@ class TimecodeFormat(
|
|||||||
|
|
||||||
def smpte_to_frame_count(
|
def smpte_to_frame_count(
|
||||||
smpte_rep_string: str, frames_per_logical_second: int, drop_frame_hint=False
|
smpte_rep_string: str, frames_per_logical_second: int, drop_frame_hint=False
|
||||||
) -> Optional[int]:
|
) -> int | None:
|
||||||
"""
|
"""
|
||||||
Convert a string with a SMPTE timecode representation into a frame count.
|
Convert a string with a SMPTE timecode representation into a frame count.
|
||||||
|
|
||||||
@@ -83,7 +85,7 @@ def frame_count_to_smpte(
|
|||||||
frame_count: int,
|
frame_count: int,
|
||||||
frames_per_logical_second: int,
|
frames_per_logical_second: int,
|
||||||
drop_frame: bool = False,
|
drop_frame: bool = False,
|
||||||
fractional_frame: Optional[float] = None,
|
fractional_frame: float | None = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
assert frames_per_logical_second in [24, 25, 30, 48, 50, 60]
|
assert frames_per_logical_second in [24, 25, 30, 48, 50, 60]
|
||||||
assert fractional_frame is None or fractional_frame < 1.0
|
assert fractional_frame is None or fractional_frame < 1.0
|
||||||
@@ -104,20 +106,21 @@ def frame_count_to_smpte(
|
|||||||
ss, ff = divmod(rem, frames_per_logical_second)
|
ss, ff = divmod(rem, frames_per_logical_second)
|
||||||
|
|
||||||
hh = hh % 24
|
hh = hh % 24
|
||||||
|
|
||||||
|
hh = int(hh)
|
||||||
|
mm = int(mm)
|
||||||
|
ss = int(ss)
|
||||||
|
ff = int(ff)
|
||||||
|
|
||||||
if fractional_frame is not None and fractional_frame > 0:
|
if fractional_frame is not None and fractional_frame > 0:
|
||||||
return "%02i:%02i:%02i%s%02i%s" % (
|
fpart = "{fractional_frame:.3f}"[1:]
|
||||||
hh,
|
return f"{hh:02}:{mm:02}:{ss:02}{separator}{ff:02}{fpart}"
|
||||||
mm,
|
|
||||||
ss,
|
|
||||||
separator,
|
|
||||||
ff,
|
|
||||||
("%.3f" % fractional_frame)[1:],
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
return "%02i:%02i:%02i%s%02i" % (hh, mm, ss, separator, ff)
|
return f"{hh:02}:{mm:02}:{ss:02}{separator}{ff:02}"
|
||||||
|
# "%02i:%02i:%02i%s%02i" % (hh, mm, ss, separator, ff)
|
||||||
|
|
||||||
|
|
||||||
def footage_to_frame_count(footage_string) -> Optional[int]:
|
def footage_to_frame_count(footage_string) -> int | None:
|
||||||
m = re.search(r"(\d+)\+(\d+)(\.\d+)?", footage_string)
|
m = re.search(r"(\d+)\+(\d+)(\.\d+)?", footage_string)
|
||||||
if m is None:
|
if m is None:
|
||||||
return None
|
return None
|
||||||
@@ -131,4 +134,4 @@ def footage_to_frame_count(footage_string) -> Optional[int]:
|
|||||||
|
|
||||||
def frame_count_to_footage(frame_count):
|
def frame_count_to_footage(frame_count):
|
||||||
feet, frm = divmod(frame_count, 16)
|
feet, frm = divmod(frame_count, 16)
|
||||||
return "%i+%02i" % (feet, frm)
|
return f"{feet}+{frm:02}"
|
||||||
|
|||||||
+19
-21
@@ -3,6 +3,8 @@ This module provides the main input document parsing and transform
|
|||||||
implementation.
|
implementation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import csv
|
import csv
|
||||||
import datetime
|
import datetime
|
||||||
import os
|
import os
|
||||||
@@ -11,7 +13,7 @@ from collections.abc import Iterator
|
|||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
from json import JSONEncoder
|
from json import JSONEncoder
|
||||||
from typing import List, Optional
|
from zoneinfo import ZoneInfo
|
||||||
|
|
||||||
import ptsl
|
import ptsl
|
||||||
|
|
||||||
@@ -39,26 +41,25 @@ class FractionEncoder(JSONEncoder):
|
|||||||
as a dict.
|
as a dict.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
force_denominator: Optional[int]
|
force_denominator: int | None
|
||||||
|
|
||||||
def default(self, o):
|
def default(self, o):
|
||||||
""" """
|
|
||||||
if isinstance(o, Fraction):
|
if isinstance(o, Fraction):
|
||||||
return dict(numerator=o.numerator, denominator=o.denominator)
|
return {"numerator": o.numerator, "denominator": o.denominator}
|
||||||
else:
|
else:
|
||||||
return o.__dict__
|
return o.__dict__
|
||||||
|
|
||||||
|
|
||||||
def output_adr_csv(lines: List[ADRLine], time_format: TimecodeFormat):
|
def output_adr_csv(lines: list[ADRLine], time_format: TimecodeFormat):
|
||||||
"""
|
"""
|
||||||
Writes ADR lines as CSV to the current working directory. Creates
|
Writes ADR lines as CSV to the current working directory. Creates
|
||||||
directories for each character number and name pair, and within that
|
directories for each character number and name pair, and within that
|
||||||
directory, creates a CSV file for each reel.
|
directory, creates a CSV file for each reel.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
reels: set[str | None] = set([ln.reel for ln in lines])
|
reels: set[str | None] = {ln.reel for ln in lines}
|
||||||
for n, name in [(n.character_id, n.character_name) for n in lines]:
|
for n, name in [(n.character_id, n.character_name) for n in lines]:
|
||||||
dir_name = "%s_%s" % (n, name)
|
dir_name = f"{n}_{name}"
|
||||||
os.makedirs(dir_name, exist_ok=True)
|
os.makedirs(dir_name, exist_ok=True)
|
||||||
os.chdir(dir_name)
|
os.chdir(dir_name)
|
||||||
for reel in reels:
|
for reel in reels:
|
||||||
@@ -69,11 +70,8 @@ def output_adr_csv(lines: List[ADRLine], time_format: TimecodeFormat):
|
|||||||
if len(these_lines) == 0:
|
if len(these_lines) == 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
outfile_name = "%s_%s_%s_%s.csv" % (
|
outfile_name = (
|
||||||
these_lines[0].title,
|
f"{these_lines[0].title}_{n}_{these_lines[0].character_name}_{reel}.csv"
|
||||||
n,
|
|
||||||
these_lines[0].character_name,
|
|
||||||
reel,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
with open(outfile_name, mode="w", newline="") as outfile:
|
with open(outfile_name, mode="w", newline="") as outfile:
|
||||||
@@ -119,13 +117,13 @@ def output_adr_csv(lines: List[ADRLine], time_format: TimecodeFormat):
|
|||||||
os.chdir("..")
|
os.chdir("..")
|
||||||
|
|
||||||
|
|
||||||
def generate_documents(session_tc_format, scenes, adr_lines: List[ADRLine], title):
|
def generate_documents(session_tc_format, scenes, adr_lines: list[ADRLine], title):
|
||||||
"""
|
"""
|
||||||
Create PDF output.
|
Create PDF output.
|
||||||
"""
|
"""
|
||||||
print_section_header_style("Creating PDF Reports")
|
print_section_header_style("Creating PDF Reports")
|
||||||
report_date = datetime.datetime.now()
|
report_date = datetime.datetime.now()
|
||||||
reports_dir = "%s_%s" % (title, report_date.strftime("%Y-%m-%d_%H%M%S"))
|
reports_dir = f"{title}_{report_date.strftime('%Y-%m-%d_%H%M%S')}"
|
||||||
os.makedirs(reports_dir, exist_ok=False)
|
os.makedirs(reports_dir, exist_ok=False)
|
||||||
os.chdir(reports_dir)
|
os.chdir(reports_dir)
|
||||||
|
|
||||||
@@ -155,7 +153,7 @@ def generate_documents(session_tc_format, scenes, adr_lines: List[ADRLine], titl
|
|||||||
|
|
||||||
|
|
||||||
def create_adr_reports(
|
def create_adr_reports(
|
||||||
lines: List[ADRLine], tc_display_format: TimecodeFormat, reel_list: List[str]
|
lines: list[ADRLine], tc_display_format: TimecodeFormat, reel_list: list[str]
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Creates a directory heirarchy and a respective set of ADR reports,
|
Creates a directory heirarchy and a respective set of ADR reports,
|
||||||
@@ -240,18 +238,18 @@ def convert(major_mode, input_file=None, output=sys.stdout, warnings=True):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# TODO: Breakdown by titles
|
# TODO: Breakdown by titles
|
||||||
titles = set([x.title for x in (generic_events + adr_lines)])
|
titles = {x.title for x in (generic_events + adr_lines)}
|
||||||
if len(titles) != 1:
|
if len(titles) != 1:
|
||||||
print_warning(
|
print_warning(
|
||||||
"Multiple titles per export is not supported, "
|
"Multiple titles per export is not supported, "
|
||||||
"found multiple titles: %s Exiting." % titles
|
f"found multiple titles: {titles} Exiting."
|
||||||
)
|
)
|
||||||
exit(-1)
|
sys.exit(-1)
|
||||||
|
|
||||||
title = list(titles)[0]
|
title = next(iter(titles))
|
||||||
|
|
||||||
print_status_style("%i generic events found." % len(generic_events))
|
print_status_style(f"{len(generic_events)} generic events found.")
|
||||||
print_status_style("%i ADR events found." % len(adr_lines))
|
print_status_style(f"{len(adr_lines)} ADR events found.")
|
||||||
|
|
||||||
if warnings:
|
if warnings:
|
||||||
perform_adr_validations(iter(adr_lines))
|
perform_adr_validations(iter(adr_lines))
|
||||||
|
|||||||
Reference in New Issue
Block a user