Skip to content

Instantly share code, notes, and snippets.

@vankasteelj
Created November 10, 2015 20:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vankasteelj/39723be4a99fc2d151b1 to your computer and use it in GitHub Desktop.
Save vankasteelj/39723be4a99fc2d151b1 to your computer and use it in GitHub Desktop.
transcode .ass, .ssa, .txt to SRT
//transcode .ass, .ssa, .txt to SRT
var convert2srt = function (file, ext, callback) {
var readline = require('readline'),
counter = null,
lastBeginTime,
//input
orig = /([^\\]+)$/.exec(file)[1],
origPath = file.substr(0, file.indexOf(orig)),
//output
srt = orig.replace(ext, '.srt'),
srtPath = Settings.tmpLocation,
//elements
dialog, begin_time, end_time;
fs.writeFileSync(path.join(srtPath, srt), ''); //create or delete content;
console.debug('SUB format can be converted:', orig);
var rl = readline.createInterface({
input: fs.createReadStream(path.join(origPath, orig)),
output: process.stdout,
terminal: false
});
rl.on('line', function (line) {
//detect encoding
var charset = charsetDetect.detect(line);
var encoding = charset.encoding;
var line_, parsedBeginTime, parsedEndTime, parsedDialog;
//parse SSA
if (ext === '.ssa' || ext === '.ass') {
encoding = 'utf-8';
if (line.indexOf('Format:') !== -1) {
var ssaFormat = line.split(',');
for (var i = 0; i < ssaFormat.length; i++) {
switch (ssaFormat[i]) {
case 'Text':
case ' Text':
dialog = i;
break;
case 'Start':
case ' Start':
begin_time = i;
break;
case 'End':
case ' End':
end_time = i;
break;
default:
}
}
if (dialog && begin_time && end_time) {
console.debug('SUB formatted in \'ssa\'');
}
return; //we have the elms spots, move on to the next line
}
if (line.indexOf('Dialogue:') === -1) { //not a dialog line
return;
}
line_ = line.split(',');
parsedBeginTime = line_[begin_time];
parsedEndTime = line_[end_time];
parsedDialog = line_[dialog];
parsedDialog = parsedDialog.replace('{\\i1}', '<i>').replace('{\\i0}', '</i>'); //italics
parsedDialog = parsedDialog.replace('{\\b1}', '<b>').replace('{\\b0}', '</b>'); //bold
parsedDialog = parsedDialog.replace('\\N', '\n'); //return to line
parsedDialog = parsedDialog.replace(/{.*?}/g, ''); //remove leftovers brackets
}
//parse TXT
if (ext === '.txt') {
line_ = line.split('}');
var formatSeconds = function (seconds) {
var date = new Date(1970, 0, 1);
date.setSeconds(seconds);
return date.toTimeString().replace(/.*(\d{2}:\d{2}:\d{2}).*/, '$1');
};
parsedBeginTime = formatSeconds(line_[0].replace('{', '') / 25);
parsedEndTime = formatSeconds(line_[1].replace('{', '') / 25);
parsedDialog = line_[2].replace('|', '\n');
}
//SRT needs a number for each subtitle
counter += 1;
//keep only the last lang
if (parsedBeginTime < lastBeginTime) {
counter = 1;
fs.writeFileSync(path.join(srtPath, srt), '');
console.debug('SUB contains multiple tracks, keeping only the last');
}
//SRT formatting
var parsedLine =
counter + '\n' +
parsedBeginTime + ' --> ' + parsedEndTime + '\n' +
parsedDialog;
fs.appendFileSync(path.join(srtPath, srt), '\n\n' + parsedLine, encoding);
lastBeginTime = parsedBeginTime;
});
setTimeout(function () {
fs.readFile(path.join(srtPath, srt), function (err, dataBuff) {
if (!err) {
console.debug('SUB transcoded to SRT:', srt);
callback(dataBuff);
} else {
console.warn('SUB transcoding failed', err);
}
});
}, 2000);
};
@vankasteelj
Copy link
Author

It is crappy and needs serious rewrite, but I scavenged that from popcorntime and found it useful, although I have nor the time nor the will to rewrite it or deeply analyze it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment