Source Code
var fps = 24.00
var event_counter = 0
var new_fps = 0
function frames2tcf(framenumber, framerate) { //frames to timecode format 00:01:02:24
var seconds_float = framenumber / framerate //to make it easier to calibrate FPS
var seconds_int = Math.floor(seconds_float) //right now our best calibration technique
var seconds_frac = seconds_float - seconds_int //is making sure the :00 frames events in Originator
var frames = Math.round(seconds_frac * framerate) + '' //export as ,000 timecode SRT
var date = new Date(0); //and vice versa
date.setSeconds(seconds_int);
var timeString = date.toISOString().substr(11, 8)
if(frames.length == 1) frames = "0"+frames //to make sure frames count as 01, 02, etc.
var timecodef = timeString + ":" + frames
return timecodef
}
function tc2frames(timeString, framerate) { //timecode format 00:01:02,000 to frames
var timeArray = timeString.split(":")
var hours = parseInt(timeArray[0]) * 60 * 60
var minutes = parseInt(timeArray[1]) * 60
var s_ms = timeArray[2].split(",")
var seconds = parseInt(s_ms[0])
var ms = parseInt(s_ms[1])
var totalTime = hours + minutes + seconds + ms / 1000
var totalFrames = Math.round(totalTime * fps)
return totalFrames
}
function uid() { //gratefully stolen from Chrome source code
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11)
.replace(/[018]/g, c => (c ^ crypto.getRandomValues(
new Uint8Array(1))[0] & 15 >> c / 4)
.toString(16))
}
function isInt(value) { //to avoid int conversion in the main code -- we need it as string
value = value * 1
if (value === parseInt(value, 10)) return true
return false
}
function setFPS() { //icky, but at least it takes almost any input and doesn't break
var new_fps = prompt("Current FPS set to: " + fps +
"\nPress Enter to keep current FPS or enter new, e.g. 2500 or 2397 or 2997:",
"2400")
if (new_fps === null) var new_fps = 2400
new_fps = new_fps.replace(".", "")
new_fps = new_fps.replace(",", "")
if (new_fps.length == 2) new_fps = new_fps + "00"
new_fps = (new_fps.substr(0, 2) + "." + new_fps.substr(2)) * 1
if (new_fps !== fps) {
fps = new_fps
alert("FPS set to: " + fps)
}
}
function stylify(text) { //recursively returns styles: {"type":"italic", "from": INT, "to":INT AS STRING}
var style_arr = [] //suitable for multiple tags in one event
var styleobj = {}
do {
from = text.indexOf("<i>")
text = text.replace("<i>", "")
to = text.indexOf("</i>")
text = text.replace("</i>", "")
if (from !== -1 && to !== -1) {
styleobj = {
type: "italic"
, from: from
, to: to
}
style_arr.push(styleobj)
}
styleobj = {}
} while (text.indexOf("<i>") !== -1)
return style_arr
}
function srtPrepare() {
var start_previous = 0
var end_previous = 0
var allEvents = document.getElementById('srt')
.value.split("\n\n")
var values = []
setFPS()
for (event of allEvents) {
var style_obj = {}
var style_arr = []
var event_lines = event.split("\n")
if (!isInt(event_lines[0]) || !event_lines[1].includes(
"-->")) {
alert("Invalid event in SRT:\n0: " + event_lines[0] +
"\n1: " + event_lines[1] + "\nEvent: " + event)
setTimeout(function () {
location.reload();
}, 3000)
throw new Error("Invalid SRT!")
}
var timecode = event_lines[1].replace(/\\./g, ",")
var start = timecode.split("-->")[0].trim()
start = tc2frames(start)
var end = timecode.split("-->")[1].trim()
end = tc2frames(end)
delta_start = start - start_previous
delta_end = end - end_previous
if (delta_start < 0 || delta_end <= 0 || delta_start > 7200 ||
delta_end > 7200) {
alert("Funky timecodes in event " + event + //7200 is a hard-coded value
"\n This event in-cue: " + start + //approx 5 min max gap between events
"; previous event in-cue: " + start_previous + //because the Originator WILL break
"\nThis event out-cue: " + end + //if given a value of, say, 99999999 frames
"; previous event out-cue: " + end_previous)
setTimeout(function () {
location.reload();
}, 3000)
throw new Error(
"Timecodes wrong--either not sequential or too large a gap between"
)
}
if (delta_start === 0) start += 2 //frame gap of 2 added automatically
event_lines.splice(0, 2)
var txt = event_lines.join("\n")
.trim()
var rgn = "bottom"
if (txt.indexOf("{\\an8}") !== -1) {
rgn = "top"
}
txt = txt.replace(/\{.an.\}/g, "")
var styles = stylify(txt)
txt = txt.replace(/<i>/g, "")
txt = txt.replace(/<\/i>/g, "")
var editedByUser = true
var markup = []
var annotations = {}
var rubies = {}
var validations = {}
var knp = []
var id = uid()
var eventType = "TIMED_TEXT_EVENT"
var subtitle = {
id: id
, start: start
, end: end
, txt: txt
, eventType: eventType
, rgn: rgn
, styles: styles
, editedByUser: editedByUser
, markup: markup
, annotations: annotations
, rubies: rubies
, validations: validations
, knp: knp
}
values.push(subtitle)
start_previous = start
end_previous = end
event_counter++
}
var result = {
type: "CLIPBOARD_VALUES"
, values: values
}
json_events = JSON.stringify(result)
alert("Press Enter and Ctrl+C")
document.addEventListener('copy', function (e) {
e.clipboardData.setData('application/json',
json_events)
e.preventDefault()
alert("Copied " + event_counter + " events at FPS " +
fps)
event_counter = 0
location.reload();
setTimeout(function () {
}, 3000)
})
}