From 6efcc0dabe5cee388af684c63dab1ecf0bb2769a Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Tue, 26 Oct 2021 13:48:57 -0700 Subject: [PATCH] Added subtitle Signed-off-by: James Ketrenos --- subtitle-extract | 104 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100755 subtitle-extract diff --git a/subtitle-extract b/subtitle-extract new file mode 100755 index 0000000..8eeda91 --- /dev/null +++ b/subtitle-extract @@ -0,0 +1,104 @@ +#!/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)); +});