Adjust handling of FCP/DaVinci Resolve timeline XML file content (#839)

* Adjust handling of FCP/DaVinci Resolve timeline XML file content

Check for element existence and handle alternative format (not having project.children hierarchy).

* make more DRY

* add test

Co-authored-by: marco rolappe <m_rolappe@web.de>
Co-authored-by: Mikael Finstad <finstaden@gmail.com>
pull/949/head
Marco Rolappe 2021-11-15 14:46:30 +01:00 zatwierdzone przez GitHub
rodzic 7c6a1607c1
commit 5e0f6e1a63
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
4 zmienionych plików z 1459 dodań i 1 usunięć

Wyświetl plik

@ -28,3 +28,44 @@ Array [
},
]
`;
exports[`parses xmeml 2 1`] = `
Array [
Object {
"end": 2033.5666666666666,
"start": 5.1,
},
Object {
"end": 3839.2833333333333,
"start": 3017.7,
},
Object {
"end": 4686.366666666667,
"start": 3862.9333333333334,
},
Object {
"end": 6310.016666666666,
"start": 5324.066666666667,
},
Object {
"end": 6959.516666666666,
"start": 6928.15,
},
Object {
"end": 8081.116666666667,
"start": 6985.9,
},
Object {
"end": 9750.05,
"start": 8728.066666666668,
},
Object {
"end": 10545.116666666667,
"start": 9793.316666666668,
},
Object {
"end": 10864.883333333333,
"start": 10740.633333333333,
},
]
`;

Wyświetl plik

@ -5,6 +5,7 @@ import csvParse from 'csv-parse';
import pify from 'pify';
import sortBy from 'lodash/sortBy';
import _ from 'lodash';
import { formatDuration } from './util/duration';
import { invertSegments, sortSegments } from './segments';
@ -107,8 +108,21 @@ export function parsePbf(text) {
// https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/FinalCutPro_XML/VersionsoftheInterchangeFormat/VersionsoftheInterchangeFormat.html
export function parseXmeml(xmlStr) {
const xml = fastXmlParser.parse(xmlStr);
// TODO maybe support media.audio also?
return xml.xmeml.project.children.sequence.media.video.track.clipitem.map((item) => ({ start: item.start / item.rate.timebase, end: item.end / item.rate.timebase }));
const { xmeml } = xml;
if (!xmeml) throw Error('Root element <xmeml> not found in file');
let sequence;
if (_.property('project.children.sequence.media.video.track.clipitem')(xmeml)) {
sequence = xmeml.project.children.sequence;
} else if (_.property('sequence.media.video.track.clipitem')(xmeml)) {
sequence = xmeml.sequence;
} else {
throw Error('No <clipitem> elements found in file');
}
return sequence.media.video.track.clipitem.map((item) => ({ start: item.in / item.rate.timebase, end: item.out / item.rate.timebase }));
}
export function parseYouTube(str) {

Wyświetl plik

@ -135,3 +135,7 @@ it('parseMplayerEdl, starting at 0', async () => {
it('parses xmeml 1', async () => {
expect(await parseXmeml(await readFixture('Final Cut Pro XMEML.xml'))).toMatchSnapshot();
});
it('parses xmeml 2', async () => {
expect(await parseXmeml(await readFixture('Final Cut Pro XMEML 2.xml'))).toMatchSnapshot();
});