Añadir make_desc.py

This commit is contained in:
2026-04-11 02:16:42 +00:00
parent 707c51301f
commit cc228136aa

104
make_desc.py Normal file
View 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")