implement basic OTIO importer #2441 #1340

pull/2465/head
Mikael Finstad 1 year ago
parent b82b9439bd
commit eea51da3d5
No known key found for this signature in database
GPG Key ID: 25AB36E3E81CBC26

@ -12,6 +12,65 @@ Subtitle 2 line 2
"
`;
exports[`otio 1`] = `
[
{
"end": 4.5,
"name": "2004-2-汐洛定制女包专营店.mp4",
"start": 0,
"tags": {
"otioClip": "2",
"otioTrack": "1",
},
},
{
"end": 482.23333333333335,
"name": "2004-2-汐洛定制女包专营店.mp4",
"start": 66.36666666666666,
"tags": {
"otioClip": "2",
"otioTrack": "1",
},
},
{
"end": 66.36666666666667,
"name": "2004-2-汐洛定制女包专营店.mp4",
"start": 4.5,
"tags": {
"otioClip": "2",
"otioTrack": "1",
},
},
{
"end": 4.5,
"name": "2004-2-汐洛定制女包专营店.mp4",
"start": 0,
"tags": {
"otioClip": "2",
"otioTrack": "1",
},
},
{
"end": 482.23333333333335,
"name": "2004-2-汐洛定制女包专营店.mp4",
"start": 66.36666666666666,
"tags": {
"otioClip": "2",
"otioTrack": "1",
},
},
{
"end": 66.36666666666667,
"name": "2004-2-汐洛定制女包专营店.mp4",
"start": 4.5,
"tags": {
"otioClip": "2",
"otioTrack": "1",
},
},
]
`;
exports[`parseGpsLine 1`] = `
{
"alt": 19,

@ -1,7 +1,8 @@
import { it, describe, expect, test } from 'vitest';
import { parseSrtToSegments, formatSrt, parseYouTube, formatYouTube, parseMplayerEdl, parseXmeml, parseFcpXml, parseCsv, parseCsvTime, getFrameValParser, formatCsvFrames, getFrameCountRaw, parsePbf, parseDvAnalyzerSummaryTxt, parseCutlist, parseGpsLine } from './edlFormats';
import { parseSrtToSegments, formatSrt, parseYouTube, formatYouTube, parseMplayerEdl, parseXmeml, parseFcpXml, parseCsv, parseCsvTime, getFrameValParser, formatCsvFrames, getFrameCountRaw, parsePbf, parseDvAnalyzerSummaryTxt, parseCutlist, parseGpsLine, Otio, parseOtio } from './edlFormats';
import { readFixture, readFixtureBinary } from './test/util';
import otioFixture from './test/fixtures/otio';
const expectYouTube1 = [
@ -334,3 +335,7 @@ test('parseGpsLine', () => {
// https://github.com/mifi/lossless-cut/issues/2072#issuecomment-2325755148
expect(parseGpsLine('F/2.8, SS 678.52, ISO 100, EV 0, DZOOM 1.000, GPS (-3.9130, 56.5019, 26), D 0.57m, H 102.40m, H.S 0.00m/s, V.S -0.00m/s')).toMatchSnapshot();
});
test('otio', () => {
expect(parseOtio(otioFixture satisfies Otio)).toMatchSnapshot();
});

@ -7,10 +7,11 @@ import { parse as csvParse } from 'csv-parse/browser/esm/sync';
import { stringify as csvStringify } from 'csv-stringify/browser/esm/sync';
import sortBy from 'lodash/sortBy';
import type { ICueSheet, ITrack } from 'cue-parser/lib/types';
import { z } from 'zod';
import { formatDuration } from './util/duration';
import { invertSegments, sortSegments } from './segments';
import { GetFrameCount, SegmentBase } from './types';
import { GetFrameCount, SegmentBase, SegmentTags } from './types';
import parseCmx3600 from './cmx3600';
export const getTimeFromFrameNum = (detectedFps: number, frameNum: number) => frameNum / detectedFps;
@ -451,3 +452,61 @@ export function parseGpsLine(line: string) {
verticalSpeed: parseFloat(gpsMatch[12]!),
};
}
const otioSchema = z.object({
OTIO_SCHEMA: z.string().refine((val) => val.startsWith('Timeline.'), { message: 'Invalid OTIO schema' }),
name: z.string(),
tracks: z.object({
OTIO_SCHEMA: z.string().refine((val) => val.startsWith('Stack.'), { message: 'Invalid OTIO schema for tracks' }),
children: z.array(
z.object({
OTIO_SCHEMA: z.string().refine((val) => val.startsWith('Track.'), { message: 'Invalid OTIO schema for track' }),
children: z.array(
z.object({
OTIO_SCHEMA: z.string().refine((val) => val.startsWith('Clip.'), { message: 'Invalid OTIO schema for clip' }),
name: z.string(),
source_range: z.object({
start_time: z.object({
value: z.number(),
rate: z.number(),
}),
duration: z.object({
value: z.number(),
rate: z.number(),
}),
}),
}),
),
}),
),
}),
});
export type Otio = z.infer<typeof otioSchema>;
// implemented by OpenAI:
export function parseOtio(data: unknown): SegmentBase[] {
const schema = otioSchema.parse(data);
const segments: (SegmentBase & { tags: SegmentTags })[] = [];
schema.tracks.children.forEach((track) => {
track.children.forEach((clip) => {
const start = clip.source_range.start_time.value / clip.source_range.start_time.rate;
const duration = clip.source_range.duration.value / clip.source_range.duration.rate;
const end = start + duration;
segments.push({
start,
end,
name: clip.name,
tags: {
otioTrack: track.OTIO_SCHEMA.replace(/^Track\./, ''),
otioClip: clip.OTIO_SCHEMA.replace(/^Clip\./, ''),
},
});
});
});
return segments;
}

@ -3,7 +3,7 @@ import i18n from 'i18next';
import invariant from 'tiny-invariant';
import { ZodError } from 'zod';
import { parseSrtToSegments, formatSrt, parseCuesheet, parseXmeml, parseFcpXml, parseCsv, parseCutlist, parsePbf, parseEdl, formatCsvHuman, formatTsv, formatCsvFrames, formatCsvSeconds, parseCsvTime, getFrameValParser, parseDvAnalyzerSummaryTxt } from './edlFormats';
import { parseSrtToSegments, formatSrt, parseCuesheet, parseXmeml, parseFcpXml, parseCsv, parseCutlist, parsePbf, parseEdl, formatCsvHuman, formatTsv, formatCsvFrames, formatCsvSeconds, parseCsvTime, getFrameValParser, parseDvAnalyzerSummaryTxt, parseOtio } from './edlFormats';
import { askForYouTubeInput, showOpenDialog } from './dialogs';
import { getOutPath } from './util';
import { EdlExportType, EdlFileType, EdlImportType, GetFrameCount, LlcProject, llcProjectV1Schema, llcProjectV2Schema, SegmentBase, StateSegment } from './types';
@ -125,6 +125,10 @@ export async function loadLlcProject(path: string) {
return project;
}
export async function loadOtio(path: string) {
return parseOtio(JSON.parse(await readFile(path, 'utf8')));
}
export async function readEdlFile({ type, path, fps }: {
type: EdlFileType,
path: string,
@ -143,6 +147,7 @@ export async function readEdlFile({ type, path, fps }: {
if (type === 'cue') return loadCue(path);
if (type === 'pbf') return loadPbf(path);
if (type === 'srt') return loadSrt(path);
if (type === 'otio') return loadOtio(path);
if (type === 'llc') {
const project = await loadLlcProject(path);
return project.cutSegments;

@ -0,0 +1,375 @@
{
"OTIO_SCHEMA": "Timeline.1",
"metadata": {},
"name": "",
"global_start_time": null,
"tracks": {
"OTIO_SCHEMA": "Stack.1",
"metadata": {},
"name": "tracks",
"source_range": null,
"effects": [],
"markers": [],
"enabled": true,
"children": [
{
"OTIO_SCHEMA": "Track.1",
"metadata": {},
"name": "",
"source_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 0.0
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 0.0
}
},
"effects": [],
"markers": [],
"enabled": true,
"children": [],
"kind": "Video"
},
{
"OTIO_SCHEMA": "Track.1",
"metadata": {},
"name": "",
"source_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 28934.0
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 0.0
}
},
"effects": [],
"markers": [],
"enabled": true,
"children": [
{
"OTIO_SCHEMA": "Clip.2",
"metadata": {},
"name": "2004-2-汐洛定制女包专营店.mp4",
"source_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 270.0
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 0.0
}
},
"effects": [],
"markers": [],
"enabled": true,
"media_references": {
"DEFAULT_MEDIA": {
"OTIO_SCHEMA": "ExternalReference.1",
"metadata": {},
"name": "",
"available_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 34023.0
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 0.0
}
},
"available_image_bounds": null,
"target_url": "G:/汐洛定制女包/2004-2-汐洛定制女包专营店/2004-2-汐洛定制女包专营店.mp4"
}
},
"active_media_reference_key": "DEFAULT_MEDIA"
},
{
"OTIO_SCHEMA": "Clip.2",
"metadata": {},
"name": "2004-2-汐洛定制女包专营店.mp4",
"source_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 24952.0
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 3982.0
}
},
"effects": [],
"markers": [],
"enabled": true,
"media_references": {
"DEFAULT_MEDIA": {
"OTIO_SCHEMA": "ExternalReference.1",
"metadata": {},
"name": "",
"available_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 34023.0
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 0.0
}
},
"available_image_bounds": null,
"target_url": "G:/汐洛定制女包/2004-2-汐洛定制女包专营店/2004-2-汐洛定制女包专营店.mp4"
}
},
"active_media_reference_key": "DEFAULT_MEDIA"
},
{
"OTIO_SCHEMA": "Clip.2",
"metadata": {},
"name": "2004-2-汐洛定制女包专营店.mp4",
"source_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 3712.0
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 270.0
}
},
"effects": [],
"markers": [],
"enabled": true,
"media_references": {
"DEFAULT_MEDIA": {
"OTIO_SCHEMA": "ExternalReference.1",
"metadata": {},
"name": "",
"available_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 34023.0
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 0.0
}
},
"available_image_bounds": null,
"target_url": "G:/汐洛定制女包/2004-2-汐洛定制女包专营店/2004-2-汐洛定制女包专营店.mp4"
}
},
"active_media_reference_key": "DEFAULT_MEDIA"
}
],
"kind": "Video"
},
{
"OTIO_SCHEMA": "Track.1",
"metadata": {},
"name": "",
"source_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 28934.0
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 0.0
}
},
"effects": [],
"markers": [],
"enabled": true,
"children": [
{
"OTIO_SCHEMA": "Clip.2",
"metadata": {},
"name": "2004-2-汐洛定制女包专营店.mp4",
"source_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 270.0
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 0.0
}
},
"effects": [],
"markers": [],
"enabled": true,
"media_references": {
"DEFAULT_MEDIA": {
"OTIO_SCHEMA": "ExternalReference.1",
"metadata": {},
"name": "",
"available_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 34023.0
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 0.0
}
},
"available_image_bounds": null,
"target_url": "G:/汐洛定制女包/2004-2-汐洛定制女包专营店/2004-2-汐洛定制女包专营店.mp4"
}
},
"active_media_reference_key": "DEFAULT_MEDIA"
},
{
"OTIO_SCHEMA": "Clip.2",
"metadata": {},
"name": "2004-2-汐洛定制女包专营店.mp4",
"source_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 24952.0
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 3982.0
}
},
"effects": [],
"markers": [],
"enabled": true,
"media_references": {
"DEFAULT_MEDIA": {
"OTIO_SCHEMA": "ExternalReference.1",
"metadata": {},
"name": "",
"available_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 34023.0
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 0.0
}
},
"available_image_bounds": null,
"target_url": "G:/汐洛定制女包/2004-2-汐洛定制女包专营店/2004-2-汐洛定制女包专营店.mp4"
}
},
"active_media_reference_key": "DEFAULT_MEDIA"
},
{
"OTIO_SCHEMA": "Clip.2",
"metadata": {},
"name": "2004-2-汐洛定制女包专营店.mp4",
"source_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 3712.0
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 270.0
}
},
"effects": [],
"markers": [],
"enabled": true,
"media_references": {
"DEFAULT_MEDIA": {
"OTIO_SCHEMA": "ExternalReference.1",
"metadata": {},
"name": "",
"available_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 34023.0
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 0.0
}
},
"available_image_bounds": null,
"target_url": "G:/汐洛定制女包/2004-2-汐洛定制女包专营店/2004-2-汐洛定制女包专营店.mp4"
}
},
"active_media_reference_key": "DEFAULT_MEDIA"
}
],
"kind": "Audio"
},
{
"OTIO_SCHEMA": "Track.1",
"metadata": {},
"name": "",
"source_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 0.0
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 60.0,
"value": 0.0
}
},
"effects": [],
"markers": [],
"enabled": true,
"children": [],
"kind": "Audio"
}
]
}
}

@ -0,0 +1,377 @@
// https://github.com/mifi/lossless-cut/issues/2441#issuecomment-2898207795
// see also otio.json
export default {
OTIO_SCHEMA: 'Timeline.1',
metadata: {},
name: '',
global_start_time: null,
tracks: {
OTIO_SCHEMA: 'Stack.1',
metadata: {},
name: 'tracks',
source_range: null,
effects: [],
markers: [],
enabled: true,
children: [
{
OTIO_SCHEMA: 'Track.1',
metadata: {},
name: '',
source_range: {
OTIO_SCHEMA: 'TimeRange.1',
duration: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 0,
},
start_time: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 0,
},
},
effects: [],
markers: [],
enabled: true,
children: [],
kind: 'Video',
},
{
OTIO_SCHEMA: 'Track.1',
metadata: {},
name: '',
source_range: {
OTIO_SCHEMA: 'TimeRange.1',
duration: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 28934,
},
start_time: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 0,
},
},
effects: [],
markers: [],
enabled: true,
children: [
{
OTIO_SCHEMA: 'Clip.2',
metadata: {},
name: '2004-2-汐洛定制女包专营店.mp4',
source_range: {
OTIO_SCHEMA: 'TimeRange.1',
duration: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 270,
},
start_time: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 0,
},
},
effects: [],
markers: [],
enabled: true,
media_references: {
DEFAULT_MEDIA: {
OTIO_SCHEMA: 'ExternalReference.1',
metadata: {},
name: '',
available_range: {
OTIO_SCHEMA: 'TimeRange.1',
duration: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 34023,
},
start_time: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 0,
},
},
available_image_bounds: null,
target_url: 'G:/汐洛定制女包/2004-2-汐洛定制女包专营店/2004-2-汐洛定制女包专营店.mp4',
},
},
active_media_reference_key: 'DEFAULT_MEDIA',
},
{
OTIO_SCHEMA: 'Clip.2',
metadata: {},
name: '2004-2-汐洛定制女包专营店.mp4',
source_range: {
OTIO_SCHEMA: 'TimeRange.1',
duration: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 24952,
},
start_time: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 3982,
},
},
effects: [],
markers: [],
enabled: true,
media_references: {
DEFAULT_MEDIA: {
OTIO_SCHEMA: 'ExternalReference.1',
metadata: {},
name: '',
available_range: {
OTIO_SCHEMA: 'TimeRange.1',
duration: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 34023,
},
start_time: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 0,
},
},
available_image_bounds: null,
target_url: 'G:/汐洛定制女包/2004-2-汐洛定制女包专营店/2004-2-汐洛定制女包专营店.mp4',
},
},
active_media_reference_key: 'DEFAULT_MEDIA',
},
{
OTIO_SCHEMA: 'Clip.2',
metadata: {},
name: '2004-2-汐洛定制女包专营店.mp4',
source_range: {
OTIO_SCHEMA: 'TimeRange.1',
duration: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 3712,
},
start_time: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 270,
},
},
effects: [],
markers: [],
enabled: true,
media_references: {
DEFAULT_MEDIA: {
OTIO_SCHEMA: 'ExternalReference.1',
metadata: {},
name: '',
available_range: {
OTIO_SCHEMA: 'TimeRange.1',
duration: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 34023,
},
start_time: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 0,
},
},
available_image_bounds: null,
target_url: 'G:/汐洛定制女包/2004-2-汐洛定制女包专营店/2004-2-汐洛定制女包专营店.mp4',
},
},
active_media_reference_key: 'DEFAULT_MEDIA',
},
],
kind: 'Video',
},
{
OTIO_SCHEMA: 'Track.1',
metadata: {},
name: '',
source_range: {
OTIO_SCHEMA: 'TimeRange.1',
duration: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 28934,
},
start_time: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 0,
},
},
effects: [],
markers: [],
enabled: true,
children: [
{
OTIO_SCHEMA: 'Clip.2',
metadata: {},
name: '2004-2-汐洛定制女包专营店.mp4',
source_range: {
OTIO_SCHEMA: 'TimeRange.1',
duration: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 270,
},
start_time: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 0,
},
},
effects: [],
markers: [],
enabled: true,
media_references: {
DEFAULT_MEDIA: {
OTIO_SCHEMA: 'ExternalReference.1',
metadata: {},
name: '',
available_range: {
OTIO_SCHEMA: 'TimeRange.1',
duration: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 34023,
},
start_time: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 0,
},
},
available_image_bounds: null,
target_url: 'G:/汐洛定制女包/2004-2-汐洛定制女包专营店/2004-2-汐洛定制女包专营店.mp4',
},
},
active_media_reference_key: 'DEFAULT_MEDIA',
},
{
OTIO_SCHEMA: 'Clip.2',
metadata: {},
name: '2004-2-汐洛定制女包专营店.mp4',
source_range: {
OTIO_SCHEMA: 'TimeRange.1',
duration: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 24952,
},
start_time: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 3982,
},
},
effects: [],
markers: [],
enabled: true,
media_references: {
DEFAULT_MEDIA: {
OTIO_SCHEMA: 'ExternalReference.1',
metadata: {},
name: '',
available_range: {
OTIO_SCHEMA: 'TimeRange.1',
duration: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 34023,
},
start_time: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 0,
},
},
available_image_bounds: null,
target_url: 'G:/汐洛定制女包/2004-2-汐洛定制女包专营店/2004-2-汐洛定制女包专营店.mp4',
},
},
active_media_reference_key: 'DEFAULT_MEDIA',
},
{
OTIO_SCHEMA: 'Clip.2',
metadata: {},
name: '2004-2-汐洛定制女包专营店.mp4',
source_range: {
OTIO_SCHEMA: 'TimeRange.1',
duration: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 3712,
},
start_time: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 270,
},
},
effects: [],
markers: [],
enabled: true,
media_references: {
DEFAULT_MEDIA: {
OTIO_SCHEMA: 'ExternalReference.1',
metadata: {},
name: '',
available_range: {
OTIO_SCHEMA: 'TimeRange.1',
duration: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 34023,
},
start_time: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 0,
},
},
available_image_bounds: null,
target_url: 'G:/汐洛定制女包/2004-2-汐洛定制女包专营店/2004-2-汐洛定制女包专营店.mp4',
},
},
active_media_reference_key: 'DEFAULT_MEDIA',
},
],
kind: 'Audio',
},
{
OTIO_SCHEMA: 'Track.1',
metadata: {},
name: '',
source_range: {
OTIO_SCHEMA: 'TimeRange.1',
duration: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 0,
},
start_time: {
OTIO_SCHEMA: 'RationalTime.1',
rate: 60,
value: 0,
},
},
effects: [],
markers: [],
enabled: true,
children: [],
kind: 'Audio',
},
],
},
};

@ -84,7 +84,7 @@ export interface InverseCutSegment extends DefiniteSegmentBase {
export type PlaybackMode = 'loop-segment-start-end' | 'loop-segment' | 'play-segment-once' | 'loop-selected-segments';
export type EdlFileType = 'csv' | 'csv-frames' | 'cutlist' | 'xmeml' | 'fcpxml' | 'dv-analyzer-summary-txt' | 'cue' | 'pbf' | 'edl' | 'srt' | 'llc';
export type EdlFileType = 'llc' | 'csv' | 'csv-frames' | 'cutlist' | 'xmeml' | 'fcpxml' | 'dv-analyzer-summary-txt' | 'cue' | 'pbf' | 'edl' | 'srt' | 'otio';
export type EdlImportType = 'youtube' | EdlFileType;

@ -516,7 +516,7 @@ export async function readDirRecursively(dirPath: string) {
export function getImportProjectType(filePath: string) {
if (filePath.endsWith('Summary.txt')) return 'dv-analyzer-summary-txt';
const edlFormatForExtension = { csv: 'csv', pbf: 'pbf', edl: 'edl', cue: 'cue', xml: 'xmeml', fcpxml: 'fcpxml' } as const;
const edlFormatForExtension = { csv: 'csv', pbf: 'pbf', edl: 'edl', cue: 'cue', xml: 'xmeml', fcpxml: 'fcpxml', otio: 'otio' } as const;
const matchingExt = Object.keys(edlFormatForExtension).find((ext) => filePath.toLowerCase().endsWith(`.${ext}`)) as keyof typeof edlFormatForExtension | undefined;
if (!matchingExt) return undefined;
return edlFormatForExtension[matchingExt];

Loading…
Cancel
Save