Skip to content

Instantly share code, notes, and snippets.

@koreapyj
Created February 25, 2025 20:05
Show Gist options
  • Save koreapyj/35a021fb2dc88f13a918edc1d9c04a14 to your computer and use it in GitHub Desktop.
Save koreapyj/35a021fb2dc88f13a918edc1d9c04a14 to your computer and use it in GitHub Desktop.
/**
* Javascript SAMI subtitle loader
* @license GPL-3.0-or-later
* @copyright koreapyj, 2014
*/
class SAMILoader {
/**
* Item of TimedText
* @typedef {object} TimedTextItem
* @property {number} start Start time in milliseconds
* @property {string} text HTML string
*/
/** @type {number} */
delay = 0;
/** @type {boolean} */
isLoaded = false;
/** @type {Array.<TimedTextItem>} */
timedText = [];
/**
* Load SAMI subtitle string
* @param {string} sami sami string
*/
load (sami) {
var cnt = 0;
const syncs = sami.split(/<sync/gim);
for (const sync of syncs) {
if (typeof sync !== "string")
continue;
const result = sync.match(/start[^=]*=[^0-9]*([0-9]+)[^>]*>([\s\S]+)/im);
if (result === null)
continue;
const start = ~~result[1];
const text = result[2]
.replace(/<p[^>]*>/gi, "")
.replace(/<font[^>]* color=([\'\"]*)(?<color>[^>]+)\1[^>]*>(?<content>.*)<\/font>/gi, "<span style=\"color:$<color>\">$<content></span>")
.replace(/<br[^>]*>/gi, "<br>")
.replace(/[\r\n]/g, "")
.split(/<\/body>/gi)[0]
;
this.timedText[cnt].push({start,text});
cnt++;
}
this.isLoaded = true;
}
/**
* Get subtitle HTML string for current video time
* @param {number} ms Current video time in milliseconds
* @returns {string}
*/
getText (ms) {
if (!this.isLoaded)
return false;
for (i = this.timedText.length; i--;) {
if (this.timedText[i].start <= ms - this.delay) {
const now = this.timedText[i];
return now.text;
}
}
return "&nbsp;";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment