I was watching a series and had to shift my subtitles by 38 seconds every time I open a video. After a few times of pain, I ended up writing a script to cut the crap, have some fun, and get a bit into NodeJS file I/O! 😀
It only deals with subtitle files of *.ASS extension. `delay_ass.js` being the NodeJS script file, you can use it like:
$ node delay_ass.js example.ass -32
Grab it here:
// USAGE: | |
// node delay_ass.js subtitle.ass -32 | |
const fs = require('fs'); | |
const fileName = process.argv[2]; | |
const delaySeconds = process.argv[3]; | |
const encoding = process.argv[4] || 'utf16le'; | |
if (typeof delaySeconds === 'undefined') { | |
console.log( | |
'Error: Please provide a number after file name for seconds to delay, e.g.:' | |
); | |
console.log('$ node delay_ass.js S02E01.ass -12.5'); | |
return; | |
} | |
const isDelay = !delaySeconds.startsWith('-'); | |
const adjective = isDelay ? 'later' : 'earlier'; | |
fs.readFile(fileName, encoding, (err, data) => { | |
if (err) return console.log(err); | |
const dataLines = data.split(/\n/); | |
const newLines = dataLines.map(line => { | |
if (line.startsWith('Dialogue:')) { | |
return processLine(line); | |
} else { | |
return line; | |
} | |
}); | |
const newData = newLines.join('\n'); | |
fs.writeFile(fileName, newData, encoding, err => { | |
if (err) return console.log(err); | |
console.log( | |
'Successfully made subtitle appear ', | |
adjective, | |
'by', | |
delaySeconds, | |
'seconds.' | |
); | |
}); | |
}); | |
function processLine(line) { | |
const blocks = line.split(/,/); | |
const newBlocks = blocks.map((block, i) => { | |
if (i === 1 || i === 2) { | |
return delayTimestamp(block); | |
} else { | |
return block; | |
} | |
}); | |
return newBlocks.join(','); | |
} | |
function delayTimestamp(time, delayStr = delaySeconds) { | |
// E.G. 0:14:12.04 | |
const timeArr = time.split(/:/).map(e => parseFloat(e, 10)); | |
const [h, m, s] = timeArr; | |
const totalS = s + 60 * m + 3600 * h; | |
const delay = parseFloat(delayStr, 10); | |
const newTotalS = totalS + delay; | |
const newH = Math.max(0, Math.floor(newTotalS / 3600)); | |
const newM = Math.max(0, Math.floor((newTotalS % 3600) / 60)); | |
const newS = Math.max(0, newTotalS % 60); | |
const newTime = [newH, newM, newS.toFixed(2)].join(':'); | |
return newTime; | |
} |
