-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathCaptions.js
136 lines (126 loc) · 3.92 KB
/
Captions.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import { Fragment, useState } from 'react'
import Spacer from '../components/Spacer'
export default function Captions({ youTubeRef, data, videoId }) {
const [captionSearch, setCaptionSearch] = useState('')
const normalizedCaptionSearch = captionSearch.trim().toLowerCase()
const captions = data.captions.items.find(
caption =>
caption.snippet.status === 'serving' && caption.snippet.language === 'en'
)
const captionLines =
captions &&
captions.body &&
captions.body
.split('\n\n')
.map(line => {
const [range, label = ''] = line.split('\n')
return {
timestamp: range.split(',')[0],
label: label.toLowerCase().trim(),
}
})
const filteredCaptionLines =
captionLines &&
captionLines.filter(
line => line.label && line.label.indexOf(normalizedCaptionSearch) !== -1
)
return (
<Fragment>
<h2>Captions</h2>
<hr
style={{
height: 1,
backgroundColor: 'rgb(200, 200, 200)',
border: 0,
}}
/>
<Spacer size={10} />
<input
type="text"
value={captionSearch}
placeholder="Filter captions"
onChange={e => setCaptionSearch(e.target.value)}
style={{
fontSize: 18,
WebkitAppearance: 'none',
appearance: 'none',
padding: '5px 10px',
width: '100%',
alignSelf: 'center',
border: '1px solid rgb(200, 200, 200)',
borderRadius: 2,
boxSizing: 'border-box',
}}
/>
<Spacer size={5} />
{normalizedCaptionSearch && captionLines.length > 0 ? (
<div
style={{
display: 'block',
color: 'rgb(100,100,100)',
fontSize: 14,
}}>
Showing <b>{filteredCaptionLines.length}</b> captions of{' '}
<b>{captionLines.length}</b> total captions
</div>
) : null}
<Spacer size={10} />
{captionLines ? (
<div
style={{
maxHeight: 500,
overflow: 'scroll',
WebkitOverflowScrolling: 'auto',
borderBottom: '1px solid rgb(200, 200, 200)',
}}>
{filteredCaptionLines.map(({ timestamp, label }, index) => (
<div
key={timestamp + label}
tabInde={index + 10}
onClick={() => {
const [hour, minute, second] = timestamp
.split(':')
.map(parseFloat)
const wasPlaying = youTubeRef.current.player.isPlaying
youTubeRef.current.seekTo(hour * 60 * 60 + minute * 60 + second)
if (wasPlaying) {
youTubeRef.current.getInternalPlayer().playVideo()
}
}}
style={{
cursor: 'pointer',
flexDirection: 'row',
borderBottomStyle: 'solid',
borderBottomColor: 'rgb(230, 230, 230)',
borderBottomWidth:
filteredCaptionLines.length - 1 === index ? 0 : 1,
padding: '5px 0',
}}>
<span
style={{
color: 'grey',
padding: '0 10px 0 0',
WebkitFontFeatureSettings: '"tnum"',
MozFontFeatureSettings: '"tnum"',
fontFeatureSettings: '"tnum"',
}}>
{timestamp}
</span>
<span
dangerouslySetInnerHTML={{
__html: label
.split(normalizedCaptionSearch)
.join('<b>' + normalizedCaptionSearch + '</b>'),
}}
/>
</div>
))}
</div>
) : (
<div style={{ paddingTop: 10, textAlign: 'center' }}>
No captions found for the video <b>{videoId}</b>.
</div>
)}
</Fragment>
)
}