113 lines
3.2 KiB
JavaScript
113 lines
3.2 KiB
JavaScript
|
import {
|
||
|
getStream,
|
||
|
indexOf,
|
||
|
renderAllProps,
|
||
|
getStreamIndex,
|
||
|
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;
|
||
|
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")}.`
|
||
|
),
|
||
|
};
|
||
|
},
|
||
|
};
|
||
|
|
||
|
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 `<producer id="producer${
|
||
|
this.index
|
||
|
}" in="00:00:00.000" out="${this.getDuration()}">
|
||
|
${await renderAllProps(
|
||
|
Producer.prop_types,
|
||
|
this.metadata,
|
||
|
project_settings
|
||
|
)}
|
||
|
</producer>
|
||
|
`;
|
||
|
}
|
||
|
}
|