From b852bafabe7753806c1487229712573c8d9411d5 Mon Sep 17 00:00:00 2001 From: Samuel Newman <10959775+mozzius@users.noreply.github.com> Date: Fri, 2 Aug 2024 23:24:15 +0200 Subject: [PATCH] add customm cue handler --- .../util/post-embeds/VideoEmbedInner.web.tsx | 83 ++++++++++++++++++- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/src/view/com/util/post-embeds/VideoEmbedInner.web.tsx b/src/view/com/util/post-embeds/VideoEmbedInner.web.tsx index f5f47db506..851fd9ca4b 100644 --- a/src/view/com/util/post-embeds/VideoEmbedInner.web.tsx +++ b/src/view/com/util/post-embeds/VideoEmbedInner.web.tsx @@ -1,6 +1,6 @@ import React, {useEffect, useRef, useState} from 'react' import {View} from 'react-native' -import Hls from 'hls.js' +import Hls, {CuesInterface} from 'hls.js' import {atoms as a} from '#/alf' import {Controls} from './VideoWebControls' @@ -27,7 +27,7 @@ export function VideoEmbedInner({ if (!ref.current) return if (!Hls.isSupported()) throw new HLSUnsupportedError() - const hls = new Hls({capLevelToPlayerSize: true}) + const hls = new Hls({capLevelToPlayerSize: true, cueHandler}) hlsRef.current = hls hls.attachMedia(ref.current) @@ -91,3 +91,82 @@ export class HLSUnsupportedError extends Error { super('HLS is not supported') } } + +// copy-pasted from https://github.com/dailymotion/hls.js/blob/master/src/utils/cues.js +// +// modified to change the line calculation for Firefox - I've annotated the change +const cueHandler: CuesInterface = { + newCue: (track, startTime, endTime, captionScreen) => { + let row + let cue + let indenting + let indent + let text + let VTTCue = window.VTTCue || window.TextTrackCue + + const cues = [] + + for (let r = 0; r < captionScreen.rows.length; r++) { + row = captionScreen.rows[r] + indenting = true + indent = 0 + text = '' + + if (!row.isEmpty()) { + for (let c = 0; c < row.chars.length; c++) { + if (row.chars[c].uchar.match(/\s/) && indenting) { + indent++ + } else { + text += row.chars[c].uchar + indenting = false + } + } + // To be used for cleaning-up orphaned roll-up captions + row.cueStartTime = startTime + + // Give a slight bump to the endTime if it's equal to startTime to avoid a SyntaxError in IE + if (startTime === endTime) { + endTime += 0.0001 + } + + cue = new VTTCue(startTime, endTime, fixLineBreaks(text.trim())) + + if (indent >= 16) { + indent-- + } else { + indent++ + } + + // VTTCue.line get's flakey when using controls, so let's now include line 13&14 + // also, drop line 1 since it's to close to the top + if (navigator.userAgent.match(/Firefox\//)) { + cue.line = -2 + } else { + cue.line = r > 7 ? r - 2 : r + 1 + } + + cue.align = 'left' + // Clamp the position between 0 and 100 - if out of these bounds, Firefox throws an exception and captions break + cue.position = Math.max( + 0, + Math.min( + 100, + 100 * (indent / 32) + + (navigator.userAgent.match(/Firefox\//) ? 50 : 0), + ), + ) + // modified - they had a type error + cues.push(cue) + if (track) { + track.addCue(cue) + } + } + } + + return cues + }, +} + +function fixLineBreaks(input: string) { + return input.replace(//gi, '\n') +}