diff --git a/audio_props.mjs b/audio_props.mjs deleted file mode 100644 index 3ddfbc9..0000000 --- a/audio_props.mjs +++ /dev/null @@ -1,13 +0,0 @@ -const audio_props = { - "stream.handler_name.markup": "SoundHandler", - "stream.type": "audio", - "codec.sample_fmt": (metadata) => { - const type = metadata.data.Format_Settings_Sign == "Signed" ? "s" : "u"; - const bit_depth = metadata.data.BitDepth; - return `${type}${bit_depth}`; - }, - "codec.channels": (metadata) => metadata.data.Channels, - "codec.sample_rate": (metadata) => metadata.data.SamplingRate, -}; - -export default audio_props; diff --git a/kdenlive.mjs b/kdenlive.mjs index 3309abc..b0e708a 100755 --- a/kdenlive.mjs +++ b/kdenlive.mjs @@ -3,21 +3,26 @@ import { formatDuration } from "./util.mjs"; import Producer from "./producer.mjs"; -export default async function kdenliveProject( - source_files, - project_settings, // const project_settings = { fps: 30 }; - clips -) { - const producers = await Promise.all(source_files.map(Producer.fromFile)); - return ` +export default class Project { + constructor(fps) { + this.producers = []; + this.clips = []; + this.fps = fps; + } + + addProducer(file) { + this.producers.push(new Producer(file)); + return this; + } + + async toXML() { + return ` ${( - await Promise.all( - producers.map((producer) => producer.toXML(project_settings)) - ) + await Promise.all(this.producers.map((producer) => producer.toXML(this.fps))) ).join("\n")} 2 @@ -29,15 +34,12 @@ ${( ] 21.08.1 - 1.02 +g 1.02 1 -${producers - .map( - (producer, index) => - `` - ) +${this.producers + .map((producer) => ``) .join("\n")} @@ -51,6 +53,8 @@ ${producers 1 + + 1 @@ -93,12 +97,12 @@ ${producers `; + } } -const project_content = await kdenliveProject( - ["/home/kuba/Videos/5min.mp4", "/home/kuba/Videos/5min.wav"], - { - fps: 30, - } -); -await $`echo ${project_content} > project-generated.kdenlive`; +const project = new Project(30); + +project.addProducer("/home/kuba/Videos/5min.mp4"); +project.addProducer("/home/kuba/Videos/5min.wav"); + +await $`echo ${await project.toXML()} > project-generated.kdenlive`; diff --git a/producer.mjs b/producer.mjs index f4368d2..20f0b8d 100644 --- a/producer.mjs +++ b/producer.mjs @@ -6,107 +6,23 @@ import { formatDuration, } from "./util.mjs"; import { makeIDGen } from "./util.mjs"; -import video_props from "./video_props.mjs"; -import audio_props from "./audio_props.mjs"; const makeId = makeIDGen(1); const producerIndexGen = makeIDGen(0); export default class Producer { - constructor(metadata) { - this.metadata = metadata; + constructor(path) { + this.path = path; this.index = producerIndexGen.next().value; } - static prop_types = { - length: (metadata, project_settings) => { - const duration = getStream(metadata.track, "General").Duration; - return `${duration * project_settings.fps}`; - }, - eof: "pause", - resource: (metadata) => metadata["@ref"], - audio_index: (metadata) => getStreamIndex(metadata.track, "Audio"), - video_index: (metadata) => getStreamIndex(metadata.track, "Video"), - mute_on_pause: "0", - mlt_service: "avformat-novalidate", - seekable: "1", - aspect_ratio: "1", - "kdenlive:clipname": "", - "kdenlive:folderid": "-1", - "kdenlive:audio_max0": "208", - "kdenlive:id": () => makeId.next().value, - "kdenlive:file_size": async (metadata) => - ( - await $`du --bytes ${metadata["@ref"]} | awk '{print $1}'` - ).stdout.replace("\n", ""), - "kdenlive:file_hash": async (metadata) => - ( - await $`head -c 1000000 ${metadata["@ref"]} && tail -c 1000000 ${metadata["@ref"]}`.pipe( - $`md5sum | awk '{print $1}'` - ) - ).stdout.replace("\n", ""), - "meta.media.nb_streams": (metadata) => metadata.track.length - 1, - $$$video: async (metadata, project_settings) => { - const video_index = indexOf(metadata.track, (e) => e["@type"] == "Video"); - if (video_index == -1) { - return null; - } - return { - $replace: await renderAllProps( - video_props, - { - index: video_index, - path: metadata["@ref"], - data: metadata.track[video_index], - }, - project_settings, - `meta.media.${getStreamIndex(metadata.track, "Video")}.` - ), - }; - }, - $$$audio: async (metadata, project_settings) => { - const audio_index = indexOf(metadata.track, (e) => e["@type"] == "Audio"); - if (audio_index == -1) { - return null; - } - return { - $replace: await renderAllProps( - audio_props, - { - index: audio_index, - path: metadata["@ref"], - data: metadata.track[audio_index], - }, - project_settings, - `meta.media.${getStreamIndex(metadata.track, "Audio")}.` - ), - }; - }, - }; + async toXML(fps) { + const xml = ( + await $`melt ${ + this.path + } -consumer xml ${`frame_rate_num=${fps}`} | htmlq producer` + ).stdout; - static async fromFile(file_path) { - const metadata = JSON.parse( - (await $`mediainfo --Output=JSON ${file_path}`).stdout - ).media; - return new Producer(metadata); - } - - getDuration() { - return formatDuration( - parseFloat(getStream(this.metadata.track, "General").Duration) - ); - } - - async toXML(project_settings) { - return ` - ${await renderAllProps( - Producer.prop_types, - this.metadata, - project_settings - )} - - `; + return xml.replace("producer0", `producer${this.index}`); } } diff --git a/util.mjs b/util.mjs index ea3058d..edb9395 100644 --- a/util.mjs +++ b/util.mjs @@ -20,7 +20,6 @@ export async function renderProperty( } else { value = await fn(metadata, project_settings); } - console.log(name, value); if (value === null) { return ""; } else if (value && value.$replace) { diff --git a/video_props.mjs b/video_props.mjs deleted file mode 100644 index 50f2a1c..0000000 --- a/video_props.mjs +++ /dev/null @@ -1,12 +0,0 @@ -const video_props = { - "stream.type": "video", - "stream.frame_rate": (metadata) => metadata.data.FrameRate, - "stream.sample_aspect_ratio": "1", - "codec.width": (metadata) => metadata.data.Width, - "codec.height": (metadata) => metadata.data.Height, - "codec.rotate": "0", - "codec.frame_rate": (metadata) => metadata.data.FrameRate, - "stream.handler_name.markup": "VideoHandle", -}; - -export default video_props \ No newline at end of file