From reading other posts it sounds like compiling MLT for Python is non-trivial because it needs to connect to other binaries, like ffmpeg, etc.?
I only want to read/write the XML from MLT, change a few values, like Title text and it’s x/y coords, then write it to a new MLT file, then send it to melt.exe to to generate a video clip.
Or, I’ll create small projects in Shotcut then use them as a template to drive the production of video files by changing some of their information. I hope all this makes sense.
My guess is I could use any XML library for this, but maybe there’s already a library and python code somewhere I could start with? Any recommendations appreciated! Thanks!
I have been working on one behind the scenes. It’s not ready for release and I don’t have it on github yet. I will soon.
At the moment I’m using this for reading the project notes and then passing those off to a text-to-speech module, as well as the OpenCV Tracker experiment. It’s only very partially implemented and needs more functionality and tests before it can be close to releasing.
# shotcutmlt.py
import sys
import re
import argparse
from bs4 import BeautifulSoup
class mltProjectFile():
def __init__(self, mlt_path):
self._mlt_path = mlt_path
self._mlt_data = None
self.read_file()
return
def read_file(self):
""" Reads the data inside the xml file
"""
with open(self._mlt_path, 'r') as f:
data = f.read()
# Passing the stored data inside the beautifulsoup parser
self._mlt_data = BeautifulSoup(data, 'xml')
return
def find_filter(self, filter_name, replace_data = None):
""" Finds a Filter by name and optionally replaces
the value
"""
print('----------------------------------------------')
a_name = bs_data.find_all('property', {'name':'shotcut:filter'})
print(a_name)
for a in a_name:
value = a.string
if value == 'affine':
if filter_name != a.parent['id']:
continue
print("Found affine ===>",value, a.parent['id'])
t_name = a.parent.find('property', {'name':'transition.rect'})
print(' transition=', t_name.string)
elif value == 'resource':
print("Found resource ===>",value)
print(" parent=",a.parent)
elif value == 'affineSizePosition':
if filter_name != a.parent['id']:
continue
print("Found affineSizePosition ===>",value, a.parent['id'])
t_name = a.parent.find('property', {'name':'transition.rect'})
print(' transition=', t_name.string)
# reading transition
transitions = {}
transitions_temp = t_name.string.split(';')
for t in transitions_temp:
splittimepos = t.split('=')
transitions[splittimepos[0]] = [float(s) for s in re.findall("[-+]?[.]?[\d]+(?:,\d\d\d)*[\.]?\d*(?:[eE][-+]?\d+)?", splittimepos[1])]
for ft in transitions:
print(' *',ft,' - ',transitions[ft])
if replace_data != None:
print('replacing transition')
t_name.string = replace_data
return t_name.string
else:
print(" name=",a['name'])
def find_notes(self, replace_data = None):
""" Finds a Filter by name and optionally replaces
the value
"""
result = None
a_name = self._mlt_data.find_all('tractor', {'id':'tractor0'})
for a in a_name:
t_name = a.parent.find('property', {'name':'shotcut:projectNote'})
result = t_name.string
return result
def write_file():
return
def bs_tree():
return self._mlt_data
if __name__ == '__main__' :
# mlt file to process
input_path = '../sjhau.info/napoleon-1/napoleon-1.mlt'
mlt = mltProjectFile(input_path)
print('----------------------------------------------')
print(mlt.find_notes())
Thanks David. I would have probably ended up using BeautifulSoup, so more reason to do so. Looks like you’re doing similar stuff so as soon as I’m functional I’ll share what I’ve coded. Thanks for your code, looks like it will already save me time!
I’m having to use a kludge because Beautiful soup, I believe, substitutes & for & when working with XML text (this Kdenlive property contains HTML). Does anyone have a better solution? THANKS! If not, this works, so can move on.
if __name__ == '__main__' :
# mlt file to process
input_path = r'C:\Max_Software\kdenlive\sample_mlt.kdenlive'
with open(input_path, 'r') as f:
data = f.read()
# Passing the stored data inside the beautifulsoup parser
mlt_xml = BeautifulSoup(data, features="xml")
xml_to_replace = mlt_xml.find('property', {'name':'xmldata'})
xml_to_replace.string = xml_to_replace.string.replace("Max Rottersman", "New Name")
# kludges because xml replaces &'s with & in HTML text of Kdenlive xmldata property;
clean_mlt_xml = str(mlt_xml)
clean_mlt_xml = str(mlt_xml).replace("&","&")
clean_mlt_xml = str(clean_mlt_xml).replace(">",">")
with open("C:\Max_Software\kdenlive\sample_mlt_new.kdenlive", "w") as file:
file.write(clean_mlt_xml)