105 lines
2.7 KiB
JavaScript
Executable File
105 lines
2.7 KiB
JavaScript
Executable File
#!/usr/bin/nodejs
|
|
const { spawn } = require('child_process'),
|
|
filename = process.argv[2],
|
|
child = spawn('ffmpeg', [
|
|
'-i', filename
|
|
]),
|
|
streams = [],
|
|
basename = filename.replace(/\.[^.]+$/, "");
|
|
|
|
let output = [];
|
|
|
|
child.stdout.on('data', (data) => {
|
|
});
|
|
|
|
child.stderr.on('data', (data) => {
|
|
output += data;
|
|
});
|
|
|
|
/*
|
|
Stream #0:2(eng): Subtitle: ass (default)
|
|
Metadata:
|
|
title : English
|
|
BPS-eng : 130
|
|
DURATION-eng : 00:47:44.040000000
|
|
...
|
|
Stream #0:4(eng): Subtitle: hdmv_pgs_subtitle
|
|
Metadata:
|
|
BPS : 3072
|
|
BPS-eng : 3072
|
|
DURATION : 00:21:51.602000000
|
|
DURATION-eng : 00:21:51.602000000
|
|
|
|
*/
|
|
|
|
let stream = undefined;
|
|
|
|
child.on('close', code => {
|
|
output.toString().split('\n').forEach(line => {
|
|
const parts = line.match(/^\s*Stream\s+#([^ ]+) Subtitle:\s*([^ ]+).*$/);
|
|
if (parts && parts.length > 0) {
|
|
/* parts[1] = '0:2(eng):'
|
|
parts[2] = 'srt'
|
|
*/
|
|
if (stream) {
|
|
streams.push(stream);
|
|
}
|
|
stream = {
|
|
extension: parts[2].replace(/hdmv_pgs_subtitle/, 'sup'), /* srt, sup */
|
|
number: parts[1].replace(/^.*([^(]+).*$/, '$1'), /* 0:2 -- not used */
|
|
language: parts[1].replace(/^[^(]*\((.*)\).*$/, '$1') /* eng */
|
|
};
|
|
return;
|
|
}
|
|
/* We tried parsing out 'title' for the langauge title, however
|
|
* that is not a consistent standard and title seems to be used
|
|
* arbitrarily. Instead, we will rely on the 'language' we parse
|
|
* from the stream name, which is specified inISO 639-1:
|
|
|
|
https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
|
|
|
|
*/
|
|
if (stream) {
|
|
if (!stream.metadata) {
|
|
if (/^\s*Metadata:.*/.exec(line)) {
|
|
stream.metadata = true;
|
|
} else {
|
|
streams.push(stream);
|
|
stream = undefined;
|
|
}
|
|
return;
|
|
}
|
|
const language = line.match(/^\s*title\s*:\s*([^\s]+)/);
|
|
if (language && language.length > 0) {
|
|
stream.language = language[1].toLowerCase();
|
|
streams.push(stream);
|
|
stream = undefined;
|
|
}
|
|
}
|
|
});
|
|
streams.forEach((stream, index) => {
|
|
const target = `${basename}.${index}_${stream.language}.${stream.extension}`,
|
|
ffmpeg = spawn('ffmpeg', [
|
|
'-i', filename,
|
|
'-c:s', 'copy',
|
|
'-map', `0:s:${index}`,
|
|
'-y',
|
|
target
|
|
]);
|
|
console.log(`0:s:${index} => ${target}`);
|
|
|
|
ffmpeg.stdout.on('data', (data) => {
|
|
console.log(data.toString());
|
|
});
|
|
|
|
ffmpeg.stderr.on('data', (data) => {
|
|
console.error(data.toString());
|
|
});
|
|
|
|
ffmpeg.on('close', code => {
|
|
console.log(`Completed: ${target} ${code}`);
|
|
});
|
|
});
|
|
console.log(JSON.stringify(streams));
|
|
});
|