Follow-up on Monkey-patching OpenTimelineIO adapter to import Final Cut Pro XML
I have several video projects from Final Cut Pro that I want to use in KdenLive. I found the OpenTimelineIO project and it would solve all my problems. I installed it, fixed the XML file following the suggestions from the thread above and am able to read with the FCP adapter.
I install opentimelineio from the PyPI, run otioconvert, and get an error related to the Kdenlive export adapter:
$ otioconvert -i /path/to/file/ep4_fixed.fcpxml -o /path/to/file/ep4_fixed.kdenlive
Traceback (most recent call last):
File "/usr/local/bin/otioconvert", line 8, in <module>
sys.exit(main())
^^^^^^
File "/usr/local/lib/python3.11/site-packages/opentimelineio/console/otioconvert.py", line 278, in main
otio.adapters.write_to_file(
File "/usr/local/lib/python3.11/site-packages/opentimelineio/adapters/__init__.py", line 192, in write_to_file
return adapter.write_to_file(
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/opentimelineio/adapters/adapter.py", line 192, in write_to_file
result = self.write_to_string(input_otio, **adapter_argument_map)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/opentimelineio/adapters/adapter.py", line 283, in write_to_string
return self._execute_function(
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/opentimelineio/plugins/python_plugin.py", line 153, in _execute_function
return (getattr(self.module(), func_name)(**kwargs))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/opentimelineio_contrib/adapters/kdenlive.py", line 389, in write_to_string
rate = input_otio.duration().rate
^^^^^^^^^^^^^^^^^^^
AttributeError: 'opentimelineio._otio.SerializableCollection' object has no attribute 'duration'
When I try to import it on Kdenlive, I get the same error:
File "/usr/local/bin/otioconvert", line 8, in <module>
sys.exit(main())
^^^^^^
File "/usr/local/lib/python3.11/site-packages/opentimelineio/console/otioconvert.py", line 278, in main
otio.adapters.write_to_file(
File "/usr/local/lib/python3.11/site-packages/opentimelineio/adapters/__init__.py", line 192, in write_to_file
return adapter.write_to_file(
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/opentimelineio/adapters/adapter.py", line 192, in write_to_file
result = self.write_to_string(input_otio, **adapter_argument_map)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/opentimelineio/adapters/adapter.py", line 283, in write_to_string
return self._execute_function(
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/opentimelineio/plugins/python_plugin.py", line 153, in _execute_function
return (getattr(self.module(), func_name)(**kwargs))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/opentimelineio_contrib/adapters/kdenlive.py", line 390, in write_to_string
rate = input_otio.duration().rate
^^^^^^^^^^^^^^^^^^^
AttributeError: 'opentimelineio._otio.SerializableCollection' object has no attribute 'duration'
The error is distinct from that thread in that the offending collection is of this sort:
SerializableCollection(ep1-6, [otio.schema.Timeline(name='ep4', tracks=otio.schema.Stack(name='', children=[otio.schema.Track(name='-1', children=[otio.schema.Gap(name='',...
How can I tweak the XML file or the source code to fix this error and export for reading in Kdenlive?
The FCP XML file is here.
update
I tried this conversion under two methods.
First, I uninstalled opentimelineio (python3 -m pip uninstaled opentimelineio) and installed it from PyPI with python3 -m pip install opentimelineio. The kdenlive adapter is listed:
$ python3 -c "import opentimelineio as otio; print(otio.adapters.available_adapter_names())"
['otio_drp_adapter', 'fcp_xml', 'otio_json', 'otioz', 'otiod', 'cmx_3600', 'svg', 'fcpx_xml', 'hls_playlist', 'rv_session', 'maya_sequencer', 'ale', 'burnins', 'AAF', 'xges', 'kdenlive']
When I run otioconvert, as above, I get the same error as above (SerializableCollection has no attribute duration).
Second, I removed that installation and installed it from source, cloning the project from GitHub, from the latest commit of the main branch (version OpenTimelineIO-0.16.0.dev1, installed with python3 -m pip install .). Then, kdenlive is not listed as an adapter, and indeed kdenlive.py is missing from the directory contrib/adapters.
Check first if this is similar to
AcademySoftwareFoundation/OpenTimelineIOissue 1694, which mentions:So you might need to tweak the OpenTimelineIO version to get the one with
durationas an attribute.Make sure the Kdenlive adapter is included in the OpenTimelineIO plugins directory and that it is correctly implemented.
Since you are working with the source code, check the
opentimelineio_contrib/adaptersdirectory for akdenlive.pyfile or similar. If you are working with the main branch, it is possible that new adapters or features are in development and not yet fully integrated or documented.Also, OpenTimelineIO uses a plugin mechanism to discover and register adapters. You can check which adapters are currently recognized by your installation with
adapters.available_adapter_names():If 'kdenlive' is not listed, the adapter is not correctly registered, which could be due to it not being included in the source code you have installed or due to an issue with the plugin discovery mechanism.
If the 'kdenlive' adapter is present in the source code but not registered, you might try manually invoking it. That would be a more complex and less recommended approach, given it bypasses the standard adapter mechanisms.
OK, so you mean the adapter is trying to call
duration()on an object it assumes to be aTimelinebut is actually aSerializableCollection. The adapter should either make sure it is operating on aTimelineobject or implement logic to handleSerializableCollectionappropriately.As a temporary workaround until the adapter issue is resolved, you might consider writing a small script that ensures the input to the
kdenliveadapter is aTimelineobject. That would involve loading the.fcpxmlfile, extracting theTimelinefrom theSerializableCollection(if necessary), and then saving that as a.kdenlivefile using the adapter programmatically.