Skip to content

Commit 230199c

Browse files
committed
Add ability to read & parse timedtext file to segments
0 parents  commit 230199c

File tree

2 files changed

+146
-0
lines changed

2 files changed

+146
-0
lines changed

index.html

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<title>Convert Youtube TimedText JSON to SRT</title>
8+
</head>
9+
<body>
10+
<div>
11+
<h3>Convert Youtube TimedText JSON to SRT</h3>
12+
<p>Upload File</p>
13+
<input type="file" onchange="read(this)"/>
14+
<pre id="msg"></pre>
15+
</div>
16+
</body>
17+
<script src="main.js"></script>
18+
</html>

main.js

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
const readFile = (file) => {
2+
return new Promise((resolve, reject) => {
3+
let fr = new FileReader();
4+
fr.onload = x=> resolve(fr.result);
5+
fr.readAsText(file);
6+
});
7+
}
8+
9+
const read = async (input) => {
10+
try {
11+
console.log('reading file contents');
12+
const textContent = await readFile(input.files[0]);
13+
console.log('done reading');
14+
const parsedSegments = await parseTimedText(textContent);
15+
// const srtData = convertSegmentsToSrt(parsedSegments);
16+
} catch (err) {
17+
console.log('error occured');
18+
console.log(err);
19+
dispayResult({
20+
isInvalid: true,
21+
content: 'Error while reading the file! Please try again'
22+
});
23+
}
24+
}
25+
26+
27+
/**
28+
* Parses stringified JSON content for getting text & time details
29+
* @param {string} txt
30+
* @returns {Array<Segment>} segments
31+
*/
32+
const parseTimedText = async (txt) => {
33+
const timedTextJson = JSON.parse(txt);
34+
const events = timedTextJson.events || [];
35+
return await getSegments(events);
36+
}
37+
38+
/**
39+
* Parses events array and returns Array of Segments containing:
40+
* (startTime, endTime, and caption text)
41+
* @param {Array<EventObject>} events
42+
* EventObject : {
43+
"tStartMs": Number,
44+
"dDurationMs": Number,
45+
"id"?: Number,
46+
"wpWinPosId"?: Number,
47+
"wsWinStyleId"?: Number,
48+
"wWinId"?: Number,
49+
"segs"?: Array<{utf8: String}>,
50+
"aAppend"?: Number
51+
}
52+
* @returns {Array<Segment>} segments
53+
* Segment: {
54+
"startTimeMs": Number,
55+
"endTimeMs": Number,
56+
"text": String
57+
}
58+
*
59+
*/
60+
const getSegments = async (events) => {
61+
62+
const segments = [];
63+
let segmentText = '';
64+
let segment = {
65+
startTimeMs: 0,
66+
};
67+
68+
events.map(evt => {
69+
70+
if (!evt.aAppend) {
71+
segment.startTimeMs = evt.tStartMs;
72+
(evt.segs || []).map(seg => {
73+
const text = seg.utf8; //.trim();
74+
if (text && text !== '\n') {
75+
segmentText += (text || '');
76+
}
77+
});
78+
79+
} else {
80+
segment.endTimeMs = evt.tStartMs;
81+
segment.text = segmentText;
82+
segments.push(segment);
83+
segment = {};
84+
segmentText = '';
85+
}
86+
87+
});
88+
89+
return segments;
90+
91+
}
92+
93+
94+
const convertToStrTime = (ms) => {
95+
96+
let seconds = Math.floor(ms / 1000);
97+
98+
ms = ms % 1000;
99+
const milliseconds = ms;
100+
101+
let minutes = Math.floor(seconds / 60);
102+
seconds = seconds % 60;
103+
104+
const hours = Math.floor(minutes / 60);
105+
minutes = minutes % 60;
106+
107+
return paddZero([hours, minutes, seconds, milliseconds]).join(':');
108+
109+
}
110+
111+
const paddZero = (numList) => {
112+
113+
if(!Array.isArray(numList)) return [];
114+
115+
return numList.map(num => {
116+
if (+num >= 10) return `${num}`;
117+
return `0${num}`;
118+
});
119+
120+
}
121+
122+
const dispayResult = (result) => {
123+
if (!result.isInvalid) {
124+
125+
} else {
126+
msg.innerText = result.content;
127+
}
128+
}

0 commit comments

Comments
 (0)