Add annotation plugin

This commit is contained in:
Chocobozzz
2020-08-21 14:46:25 +02:00
parent 47a4d19252
commit aec0c866d5
16 changed files with 4696 additions and 0 deletions

View File

@ -0,0 +1,12 @@
const shared = require('./shared-player')
function register ({ registerHook }) {
registerHook({
target: 'action:embed.player.loaded',
handler: ({ player, videojs, video }) => shared.buildPlayer(video, player, videojs)
})
}
export {
register
}

View File

@ -0,0 +1,98 @@
export function buildPlayer (video, player, videojs) {
window.videojs = videojs
require('videojs-overlay')
const fieldName = 'player-annotations'
if (!video.pluginData || !video.pluginData[fieldName]) return
const annotationsText = video.pluginData[fieldName]
const annotations = parseAnnotations(annotationsText)
if (!annotations) return
console.log('Will inject annotations in player.', annotations)
player.overlay({
overlays: annotations
})
}
function parseAnnotations (annotationsText) {
const splitted = annotationsText.split('\n\n')
return splitted.map(s => buildAnnotation(s))
.filter(a => !!a)
}
function buildAnnotation (text) {
const splitted = text.split('\n')
if (splitted.length < 2) {
console.error('Cannot build annotation %s.', text)
return undefined
}
const timestampsText = splitted.shift()
const timestamps = buildTimestamps(timestampsText)
if (!timestamps) {
console.error('Cannot build timestamp %s of %s.', timestampsText, text)
return undefined
}
let options
if (splitted[0] && (splitted[0] || '').startsWith('options:')) {
const optionsText = splitted[0]
options = buildOptions(optionsText)
if (!options) {
console.error('Cannot build options %s of %s.', optionsText, text)
} else {
splitted.shift()
}
}
const content = splitted.join('\n')
const align = options && options.align ? options.align : 'top-right'
return {
start: timestamps.start,
end: timestamps.end,
align,
content
}
}
function buildTimestamps (text) {
const result = text.split('-->')
if (result.length !== 2) return undefined
const startText = result[0].trim()
const endText = result[1].trim()
if (!startText && !endText) return undefined
let start = parseInt(startText)
let end = parseInt(endText)
if (isNaN(start)) start = undefined
if (isNaN(end)) end = undefined
if (!start && !end) return undefined
return { start, end }
}
function buildOptions (text) {
const matchedAlign = text.match(/align=([^ ]+)/)
if (matchedAlign) {
return {
align: matchedAlign[1]
}
}
return undefined
}

View File

@ -0,0 +1,21 @@
async function register ({ registerVideoField, peertubeHelpers }) {
const fieldName = 'player-annotations'
const descriptionSource = 'See <a href="https://cpy.re" target="_blank">this document</a> for annotation format'
const descriptionHTML = await peertubeHelpers.translate(descriptionSource)
const commonOptions = {
name: fieldName,
label: 'Annotations',
descriptionHTML,
type: 'input-textarea',
default: ''
}
for (const type of [ 'upload', 'import-url', 'import-torrent', 'update' ]) {
registerVideoField(commonOptions, { type })
}
}
export {
register
}

View File

@ -0,0 +1,12 @@
const shared = require('./shared-player')
function register ({ registerHook }) {
registerHook({
target: 'action:video-watch.player.loaded',
handler: ({ player, videojs, video }) => shared.buildPlayer(video, player, videojs)
})
}
export {
register
}