Merge branch 'master' of https://github.com/iluvcapra/pycmx into feat-adobe

This commit is contained in:
Jamie Hardt
2025-01-05 11:33:57 -08:00
3 changed files with 93 additions and 72 deletions

View File

@@ -20,6 +20,8 @@ class EditList:
"""
The detected format of the EDL. Possible values are: "3600", "File32",
"File128", and "unknown".
Adobe EDLs with more than 999 events will be reported as "3600".
"""
first_event = next( (s for s in self.event_statements if type(s) is StmtEvent), None)

View File

@@ -8,11 +8,11 @@ from .edit_list import EditList
from typing import TextIO
def parse_cmx3600(f: TextIO):
def parse_cmx3600(f: TextIO) -> EditList:
"""
Parse a CMX 3600 EDL.
:param TextIO f: a file-like object, anything that's readlines-able.
:param TextIO f: a file-like object, an opened CMX 3600 .EDL file.
:returns: An :class:`pycmx.edit_list.EditList`.
"""
statements = parse_cmx3600_statements(f)

View File

@@ -2,9 +2,7 @@
# (c) 2018 Jamie Hardt
import re
import sys
from collections import namedtuple
from itertools import count
from typing import TextIO, List
@@ -12,8 +10,10 @@ from .util import collimate
StmtTitle = namedtuple("Title", ["title", "line_number"])
StmtFCM = namedtuple("FCM", ["drop", "line_number"])
StmtEvent = namedtuple("Event",["event","source","channels","trans",\
"trans_op","source_in","source_out","record_in","record_out","format","line_number"])
StmtEvent = namedtuple("Event", ["event", "source", "channels", "trans",
"trans_op", "source_in", "source_out",
"record_in", "record_out", "format",
"line_number"])
StmtAudioExt = namedtuple("AudioExt", ["audio3", "audio4", "line_number"])
StmtClipName = namedtuple("ClipName", ["name", "affect", "line_number"])
StmtSourceFile = namedtuple("SourceFile", ["filename", "line_number"])
@@ -21,7 +21,8 @@ StmtRemark = namedtuple("Remark",["text","line_number"])
StmtEffectsName = namedtuple("EffectsName", ["name", "line_number"])
StmtSourceUMID = namedtuple("Source", ["name", "umid", "line_number"])
StmtSplitEdit = namedtuple("SplitEdit", ["video", "magnitude", "line_number"])
StmtMotionMemory = namedtuple("MotionMemory",["source","fps"]) # FIXME needs more fields
StmtMotionMemory = namedtuple(
"MotionMemory", ["source", "fps"]) # FIXME needs more fields
StmtUnrecognized = namedtuple("Unrecognized", ["content", "line_number"])
@@ -30,11 +31,11 @@ def parse_cmx3600_statements(file: TextIO) -> List[object]:
Return a list of every statement in the file argument.
"""
lines = file.readlines()
line_numbers = count()
return [_parse_cmx3600_line(line.strip(), line_number) \
for (line, line_number) in zip(lines,line_numbers)]
return [_parse_cmx3600_line(line.strip(), line_number)
for (line_number, line) in enumerate(lines)]
def _edl_column_widths(event_field_length, source_field_length):
def _edl_column_widths(event_field_length, source_field_length) -> List[int]:
return [event_field_length, 2, source_field_length, 1,
4, 2, # chans
4, 1, # trans
@@ -44,13 +45,19 @@ def _edl_column_widths(event_field_length, source_field_length):
11, 1,
11]
def _edl_m2_column_widths():
return [2, # "M2"
3,3, #
8,8,1,4,2,1,4,13,3,1,1]
# def _edl_m2_column_widths():
# return [2, # "M2"
# 3,3, #
# 8,8,1,4,2,1,4,13,3,1,1]
def _parse_cmx3600_line(line, line_number):
def _parse_cmx3600_line(line: str, line_number: int) -> object:
"""
Parses a single CMX EDL line.
:param line: A single EDL line.
:param line_number: The index of this line in the file.
"""
long_event_num_p = re.compile("^[0-9]{6} ")
short_event_num_p = re.compile("^[0-9]{3} ")
x_event_form_p = re.compile("^([0-9]{4,5}) ")
@@ -89,23 +96,28 @@ def _parse_cmx3600_line(line, line_number):
return _parse_unrecognized(line, line_number)
def _parse_title(line, line_num):
def _parse_title(line, line_num) -> StmtTitle:
title = line[6:].strip()
return StmtTitle(title=title, line_number=line_num)
def _parse_fcm(line, line_num):
def _parse_fcm(line, line_num) -> StmtFCM:
val = line[4:].strip()
if val == "DROP FRAME":
return StmtFCM(drop=True, line_number=line_num)
else:
return StmtFCM(drop=False, line_number=line_num)
def _parse_long_standard_form(line, source_field_length, line_number):
return _parse_columns_for_standard_form(line, 6, source_field_length, line_number)
return _parse_columns_for_standard_form(line, 6, source_field_length,
line_number)
def _parse_standard_form(line, line_number):
return _parse_columns_for_standard_form(line, 3, 8, line_number)
def _parse_extended_audio_channels(line, line_number):
content = line.strip()
if content == "AUD 3":
@@ -117,20 +129,26 @@ def _parse_extended_audio_channels(line, line_number):
else:
return StmtUnrecognized(content=line, line_number=line_number)
def _parse_remark(line, line_number) -> object:
if line.startswith("FROM CLIP NAME:"):
return StmtClipName(name=line[15:].strip() , affect="from", line_number=line_number)
return StmtClipName(name=line[15:].strip(), affect="from",
line_number=line_number)
elif line.startswith("TO CLIP NAME:"):
return StmtClipName(name=line[13:].strip(), affect="to", line_number=line_number)
return StmtClipName(name=line[13:].strip(), affect="to",
line_number=line_number)
elif line.startswith("SOURCE FILE:"):
return StmtSourceFile(filename=line[12:].strip() , line_number=line_number)
return StmtSourceFile(filename=line[12:].strip(),
line_number=line_number)
else:
return StmtRemark(text=line, line_number=line_number)
def _parse_effects_name(line, line_number) -> StmtEffectsName:
name = line[16:].strip()
return StmtEffectsName(name=name, line_number=line_number)
def _parse_split(line, line_number):
split_type = line[10:21]
is_video = False
@@ -138,7 +156,8 @@ def _parse_split(line, line_number):
is_video = True
split_mag = line[24:35]
return StmtSplitEdit(video=is_video, magnitude=split_mag, line_number=line_number)
return StmtSplitEdit(video=is_video, magnitude=split_mag,
line_number=line_number)
def _parse_motion_memory(line, line_number):
@@ -148,7 +167,9 @@ def _parse_motion_memory(line, line_number):
def _parse_unrecognized(line, line_number):
return StmtUnrecognized(content=line, line_number=line_number)
def _parse_columns_for_standard_form(line, event_field_length, source_field_length, line_number):
def _parse_columns_for_standard_form(line, event_field_length,
source_field_length, line_number):
col_widths = _edl_column_widths(event_field_length, source_field_length)
if sum(col_widths) > len(line):
@@ -165,11 +186,9 @@ def _parse_columns_for_standard_form(line, event_field_length, source_field_leng
source_out=column_strings[12].strip(),
record_in=column_strings[14].strip(),
record_out=column_strings[16].strip(),
line_number=line_number,
format=source_field_length)
line_number=line_number, format=source_field_length)
def _parse_source_umid_statement(line, line_number):
trimmed = line[3:].strip()
return StmtSourceUMID(name=None, umid=None, line_number=line_number)