Compare commits
No commits in common. "f205deb5e4de810732f66f7f0d6513710c5825ab" and "eaec1a7f86a70a0a41ae1040a73bf736377e135b" have entirely different histories.
f205deb5e4
...
eaec1a7f86
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
/.log/
|
|
108
kdenlive.mjs
108
kdenlive.mjs
@ -1,108 +0,0 @@
|
|||||||
#!/usr/bin/zx --quiet
|
|
||||||
|
|
||||||
import { formatDuration } from "./util.mjs";
|
|
||||||
import Producer from "./producer.mjs";
|
|
||||||
|
|
||||||
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 `<?xml version='1.0' encoding='utf-8'?>
|
|
||||||
<mlt LC_NUMERIC="C" producer="main_bin" version="7.0.0" root="/home/kuba/Downloads">
|
|
||||||
<profile frame_rate_num="${
|
|
||||||
this.fps
|
|
||||||
}" sample_aspect_num="1" display_aspect_den="9" colorspace="601" progressive="1" description="1920x1080 29.90fps" display_aspect_num="16" frame_rate_den="1" width="1920" height="1080" sample_aspect_den="1"/>
|
|
||||||
${(
|
|
||||||
await Promise.all(this.producers.map((producer) => producer.toXML(this.fps)))
|
|
||||||
).join("\n")}
|
|
||||||
<playlist id="main_bin">
|
|
||||||
<property name="kdenlive:docproperties.activeTrack">2</property>
|
|
||||||
<property name="kdenlive:docproperties.audioChannels">2</property>
|
|
||||||
<property name="kdenlive:docproperties.audioTarget">1</property>
|
|
||||||
<property name="kdenlive:docproperties.disablepreview">0</property>
|
|
||||||
<property name="kdenlive:docproperties.documentid">1633881496938</property>
|
|
||||||
<property name="kdenlive:docproperties.groups">[
|
|
||||||
]
|
|
||||||
</property>
|
|
||||||
<property name="kdenlive:docproperties.kdenliveversion">21.08.1</property>
|
|
||||||
g <property name="kdenlive:docproperties.version">1.02</property>
|
|
||||||
<property name="kdenlive:expandedFolders"/>
|
|
||||||
<property name="kdenlive:documentnotes"/>
|
|
||||||
<property name="xml_retain">1</property>
|
|
||||||
${this.producers
|
|
||||||
.map((producer) => `<entry producer="producer${producer.index}"/>`)
|
|
||||||
.join("\n")}
|
|
||||||
</playlist>
|
|
||||||
<producer id="black_track" in="00:00:00.000" out="00:08:20.000">
|
|
||||||
<property name="length">2147483647</property>
|
|
||||||
<property name="eof">continue</property>
|
|
||||||
<property name="resource">black</property>
|
|
||||||
<property name="aspect_ratio">1</property>
|
|
||||||
<property name="mlt_service">color</property>
|
|
||||||
<property name="mlt_image_format">rgb24a</property>
|
|
||||||
<property name="set.test_audio">0</property>
|
|
||||||
</producer>
|
|
||||||
<playlist id="playlist0">
|
|
||||||
<property name="kdenlive:audio_track">1</property>
|
|
||||||
<blank length="1000"/>
|
|
||||||
<entry producer="producer1"/>
|
|
||||||
</playlist>
|
|
||||||
<playlist id="playlist1">
|
|
||||||
<property name="kdenlive:audio_track">1</property>
|
|
||||||
</playlist>
|
|
||||||
<tractor id="tractor0" in="00:00:00.000">
|
|
||||||
<property name="kdenlive:audio_track">1</property>
|
|
||||||
<property name="kdenlive:timeline_active">1</property>
|
|
||||||
<track hide="video" producer="playlist0"/>
|
|
||||||
<track hide="video" producer="playlist1"/>
|
|
||||||
</tractor>
|
|
||||||
<playlist id="playlist2">
|
|
||||||
<property name="kdenlive:audio_track">1</property>
|
|
||||||
</playlist>
|
|
||||||
<playlist id="playlist3">
|
|
||||||
<property name="kdenlive:audio_track">1</property>
|
|
||||||
</playlist>
|
|
||||||
<tractor id="tractor1" in="00:00:00.000">
|
|
||||||
<property name="kdenlive:audio_track">1</property>
|
|
||||||
<track hide="video" producer="playlist2"/>
|
|
||||||
<track hide="video" producer="playlist3"/>
|
|
||||||
</tractor>
|
|
||||||
<playlist id="playlist4"/>
|
|
||||||
<playlist id="playlist5"/>
|
|
||||||
<tractor id="tractor2" in="00:00:00.000">
|
|
||||||
<track hide="audio" producer="playlist4"/>
|
|
||||||
<track hide="audio" producer="playlist5"/>
|
|
||||||
</tractor>
|
|
||||||
<playlist id="playlist6"/>
|
|
||||||
<playlist id="playlist7"/>
|
|
||||||
<tractor id="tractor3" in="00:00:00.000">
|
|
||||||
<track hide="audio" producer="playlist6"/>
|
|
||||||
<track hide="audio" producer="playlist7"/>
|
|
||||||
</tractor>
|
|
||||||
<tractor id="tractor4" in="00:00:00.000" out="00:08:20.000">
|
|
||||||
<track producer="black_track"/>
|
|
||||||
<track producer="tractor0"/>
|
|
||||||
<track producer="tractor1"/>
|
|
||||||
<track producer="tractor2"/>
|
|
||||||
<track producer="tractor3"/>
|
|
||||||
</tractor>
|
|
||||||
</mlt>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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`;
|
|
28
producer.mjs
28
producer.mjs
@ -1,28 +0,0 @@
|
|||||||
import {
|
|
||||||
getStream,
|
|
||||||
indexOf,
|
|
||||||
renderAllProps,
|
|
||||||
getStreamIndex,
|
|
||||||
formatDuration,
|
|
||||||
} from "./util.mjs";
|
|
||||||
import { makeIDGen } from "./util.mjs";
|
|
||||||
|
|
||||||
const makeId = makeIDGen(1);
|
|
||||||
const producerIndexGen = makeIDGen(0);
|
|
||||||
|
|
||||||
export default class Producer {
|
|
||||||
constructor(path) {
|
|
||||||
this.path = path;
|
|
||||||
this.index = producerIndexGen.next().value;
|
|
||||||
}
|
|
||||||
|
|
||||||
async toXML(fps) {
|
|
||||||
const xml = (
|
|
||||||
await $`melt ${
|
|
||||||
this.path
|
|
||||||
} -consumer xml ${`frame_rate_num=${fps}`} | htmlq producer`
|
|
||||||
).stdout;
|
|
||||||
|
|
||||||
return xml.replace("producer0", `producer${this.index}`);
|
|
||||||
}
|
|
||||||
}
|
|
83
util.mjs
83
util.mjs
@ -1,83 +0,0 @@
|
|||||||
export function indexOf(array, predicate) {
|
|
||||||
for (let i in array) {
|
|
||||||
if (predicate(array[i])) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function renderProperty(
|
|
||||||
name,
|
|
||||||
fn,
|
|
||||||
metadata,
|
|
||||||
project_settings,
|
|
||||||
prefix = ""
|
|
||||||
) {
|
|
||||||
let value;
|
|
||||||
if (typeof fn === "string") {
|
|
||||||
value = fn;
|
|
||||||
} else {
|
|
||||||
value = await fn(metadata, project_settings);
|
|
||||||
}
|
|
||||||
if (value === null) {
|
|
||||||
return "";
|
|
||||||
} else if (value && value.$replace) {
|
|
||||||
return value.$replace;
|
|
||||||
} else {
|
|
||||||
return `<property name="${prefix}${name}">${value}</property>`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function renderAllProps(
|
|
||||||
props,
|
|
||||||
metadata,
|
|
||||||
project_settings,
|
|
||||||
prefix = ""
|
|
||||||
) {
|
|
||||||
return (
|
|
||||||
await Promise.all(
|
|
||||||
Object.entries(props).map(([name, fn]) =>
|
|
||||||
renderProperty(name, fn, metadata, project_settings, prefix)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
).join("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getStream(tracks, type) {
|
|
||||||
return tracks.find((track) => track["@type"] == type);
|
|
||||||
}
|
|
||||||
|
|
||||||
const HOUR = 60 * 60;
|
|
||||||
const MINUTE = 60;
|
|
||||||
|
|
||||||
export function formatDuration(float_s) {
|
|
||||||
const hours = Math.floor(float_s / HOUR);
|
|
||||||
float_s = float_s - hours * HOUR;
|
|
||||||
const minutes = Math.floor(float_s / MINUTE);
|
|
||||||
const seconds = float_s - minutes * MINUTE;
|
|
||||||
return `${twoDigits(hours)}:${twoDigits(minutes)}:${twoDigits(seconds, 5)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function twoDigits(number, decimal = 0) {
|
|
||||||
let [int, dec] = number.toFixed(decimal).split(".");
|
|
||||||
dec = dec || "";
|
|
||||||
if (dec == "") {
|
|
||||||
return int.padStart(2, "0");
|
|
||||||
} else {
|
|
||||||
return int.padStart(2, "0") + "." + dec;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getStreamIndex(trackarray, type) {
|
|
||||||
const array_index = indexOf(trackarray, (e) => e["@type"] == type);
|
|
||||||
return array_index == -1 ? -1 : trackarray[array_index].StreamOrder || 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function* makeIDGen(first = 1) {
|
|
||||||
let i = first;
|
|
||||||
while (true) {
|
|
||||||
yield i;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user