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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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; | |
} |