Añadir make_desc.py
This commit is contained in:
104
make_desc.py
Normal file
104
make_desc.py
Normal file
@@ -0,0 +1,104 @@
|
||||
# Copyright (C) 2026 by WallyHackenslacker wallyhackenslacker@noreply.git.hackenslacker.space
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any purpose with or without
|
||||
# fee is hereby granted.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
|
||||
# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE
|
||||
# FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
# OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import xml.etree.ElementTree as ET
|
||||
import sys
|
||||
import os.path
|
||||
|
||||
|
||||
def parse_fps(value):
|
||||
text = str(value).strip()
|
||||
if "/" in text:
|
||||
numerator, denominator = text.split("/", 1)
|
||||
return float(numerator) / float(denominator)
|
||||
return float(text)
|
||||
|
||||
|
||||
def format_timestamp(position_frames, fps):
|
||||
total_seconds = int(position_frames / fps)
|
||||
hours, remainder = divmod(total_seconds, 3600)
|
||||
minutes, seconds = divmod(remainder, 60)
|
||||
|
||||
if hours > 0:
|
||||
return f"{hours}:{minutes:02d}:{seconds:02d}"
|
||||
|
||||
return f"{minutes}:{seconds:02d}"
|
||||
|
||||
|
||||
def parse_cli_args(argv, xml_fps):
|
||||
if len(argv) < 2:
|
||||
raise SystemExit("Usage: make_desc.py <tracks.xml> [fps] [output.txt]")
|
||||
|
||||
input_file = argv[1]
|
||||
fps = parse_fps(xml_fps)
|
||||
output_file = "desc.txt"
|
||||
|
||||
if len(argv) >= 3:
|
||||
try:
|
||||
fps = parse_fps(argv[2])
|
||||
if len(argv) >= 4:
|
||||
output_file = argv[3]
|
||||
except ValueError:
|
||||
output_file = argv[2]
|
||||
|
||||
return input_file, fps, output_file
|
||||
|
||||
|
||||
# Read the input file into an XML tree.
|
||||
if len(sys.argv) < 2:
|
||||
raise SystemExit("Usage: make_desc.py <tracks.xml> [fps] [output.txt]")
|
||||
|
||||
tree = ET.parse(sys.argv[1])
|
||||
root = tree.getroot()
|
||||
input_path, framerate, output_path = parse_cli_args(
|
||||
sys.argv, root.attrib.get("fps", 25.0)
|
||||
)
|
||||
|
||||
# Get all chains in the tree. Chains are media files and metadata.
|
||||
chains = {}
|
||||
|
||||
for c in tree.iter("chain"):
|
||||
chain = {}
|
||||
chain_id = None
|
||||
|
||||
for p in c:
|
||||
if p.attrib["name"] == "resource" and p.text:
|
||||
chain["file"] = os.path.basename(p.text)
|
||||
elif p.attrib["name"] == "kdenlive:id":
|
||||
if p.text:
|
||||
chain_id = int(p.text)
|
||||
elif p.attrib["name"] == "length" and p.text:
|
||||
chain["length"] = int(p.text)
|
||||
|
||||
if chain_id is not None and "file" in chain:
|
||||
chains[chain_id] = chain
|
||||
|
||||
# Get all clips in the tree. Clips are media files in the timeline.
|
||||
clips = []
|
||||
|
||||
for c in tree.iter("clip"):
|
||||
clip = {
|
||||
"position": int(c.attrib["position"]),
|
||||
"bin": int(c.attrib["binid"]),
|
||||
}
|
||||
|
||||
clips.append(clip)
|
||||
|
||||
# Sort clips by time.
|
||||
clips.sort(key=lambda x: x["position"])
|
||||
|
||||
# Write the description file.
|
||||
with open(output_path, "w") as f:
|
||||
f.write("Track list:\n")
|
||||
|
||||
for c in clips:
|
||||
timestamp = format_timestamp(c["position"], framerate)
|
||||
f.write(f"({timestamp}) {chains[c['bin']]['file']}\n")
|
||||
Reference in New Issue
Block a user