From 7241f170faf350de60d5e5320847c452fa914c21 Mon Sep 17 00:00:00 2001 From: WardPearce Date: Wed, 18 Feb 2026 19:22:32 +1300 Subject: [PATCH] More subtitle progress --- materialious/package-lock.json | 18 --- materialious/package.json | 1 - .../components/player/ClosedCaptions.svelte | 119 +++++++++++------- .../src/lib/components/player/Player.svelte | 26 ---- 4 files changed, 71 insertions(+), 93 deletions(-) diff --git a/materialious/package-lock.json b/materialious/package-lock.json index 2d321619..ed3a2f4e 100644 --- a/materialious/package-lock.json +++ b/materialious/package-lock.json @@ -21,7 +21,6 @@ "@capacitor/share": "^8.0.0", "@macfja/serializer": "^1.1.4", "@macfja/svelte-persistent-store": "^2.4.2", - "@neodrag/svelte": "^3.0.0-next.8", "altcha": "^2.3.0", "altcha-lib": "^1.4.1", "beercss": "^4.0.2", @@ -3524,23 +3523,6 @@ "node": ">= 10" } }, - "node_modules/@neodrag/core": { - "version": "3.0.0-next.8", - "resolved": "https://registry.npmjs.org/@neodrag/core/-/core-3.0.0-next.8.tgz", - "integrity": "sha512-RNFwbo2w6M7BEzCh7pls68X2h3n+ofFDW1XnGyIzhtJ2bb8J/2VqixOpOlw9NfSJ61xgUC5ymGQbQFg5BKsWBA==", - "license": "MIT", - "peer": true - }, - "node_modules/@neodrag/svelte": { - "version": "3.0.0-next.8", - "resolved": "https://registry.npmjs.org/@neodrag/svelte/-/svelte-3.0.0-next.8.tgz", - "integrity": "sha512-VkTnOqiHpAaEK5jp2PqQPEEx5AaNGVoKeoC2TuWd2xuteGOVq7NqQjNC4sxk0HAVysfYOC9YhYOsVyRiKo2LFw==", - "license": "MIT", - "peerDependencies": { - "@neodrag/core": "3.0.0-next.8", - "svelte": "^3 || ^4 || ^5" - } - }, "node_modules/@noble/hashes": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", diff --git a/materialious/package.json b/materialious/package.json index 3cb841f1..457d9e95 100644 --- a/materialious/package.json +++ b/materialious/package.json @@ -57,7 +57,6 @@ "@capacitor/share": "^8.0.0", "@macfja/serializer": "^1.1.4", "@macfja/svelte-persistent-store": "^2.4.2", - "@neodrag/svelte": "^3.0.0-next.8", "altcha": "^2.3.0", "altcha-lib": "^1.4.1", "beercss": "^4.0.2", diff --git a/materialious/src/lib/components/player/ClosedCaptions.svelte b/materialious/src/lib/components/player/ClosedCaptions.svelte index 4246ef70..75f52ad6 100644 --- a/materialious/src/lib/components/player/ClosedCaptions.svelte +++ b/materialious/src/lib/components/player/ClosedCaptions.svelte @@ -4,15 +4,11 @@ const captionTracks: Record = {}; - // Configurable settings for captions let captionFontSize: string = $state('1em'); let captionColor: string = $state('white'); let captionBackgroundColor: string = $state('rgba(0, 0, 0, 0.7)'); let captionOpacity: number = $state(1); - let captionBorderThickness: string = $state('0.1px'); - let captionBorderColor: string = $state('black'); - export function setTextTrackVisibility(visible: boolean = true) { trackVisible = visible; } @@ -22,23 +18,17 @@ fontSize, color, backgroundColor, - opacity, - borderThickness, - borderColor + opacity }: { fontSize?: string; color?: string; backgroundColor?: string; opacity?: number; - borderThickness?: string; - borderColor?: string; }) { if (fontSize) captionFontSize = fontSize; if (color) captionColor = color; if (backgroundColor) captionBackgroundColor = backgroundColor; if (opacity !== undefined) captionOpacity = opacity; - if (borderThickness) captionBorderThickness = borderThickness; - if (borderColor) captionBorderColor = borderColor; } // Fetch caption data for a selected language @@ -52,18 +42,17 @@ }); } - captionsCues = (await parseText(await resp.text(), { strict: false })).cues; + captionsCues = (await parseText(await resp.text(), { strict: true, type: 'vtt' })).cues; } {#if trackVisible && captionsCues.length > 0} - {@const currentCaption = findElementForTime( - captionsCues, - currentTime, - (cue: VTTCue) => cue.startTime, - (cue: VTTCue) => cue.endTime - )} -
[bounds(BoundsFrom.viewport()), touchAction('manipulation')])} - style="z-index: 5;cursor: grab;" - > - {#if currentCaption?.text} -

- {removeTags(currentCaption.text)} -

- {/if} -
+ {#if currentCaption && currentTime <= currentCaption.endTime && currentTime >= currentCaption.startTime} +
+ {#if currentCaption?.text} +

+ {decodeHtmlCharCodes(currentCaption.text)} +

+ {/if} +
+ {/if} {/if} + + diff --git a/materialious/src/lib/components/player/Player.svelte b/materialious/src/lib/components/player/Player.svelte index cbaa6512..4c689e34 100644 --- a/materialious/src/lib/components/player/Player.svelte +++ b/materialious/src/lib/components/player/Player.svelte @@ -17,7 +17,6 @@ import type { VideoPlay } from '$lib/api/model'; import { invidiousAuthStore, - invidiousInstanceStore, isAndroidTvStore, playerAlwaysLoopStore, playerAndroidLockOrientation, @@ -458,31 +457,6 @@ const error = (event as CustomEvent).detail as shaka.util.Error; console.error('Player error:', error); }); - player.getNetworkingEngine()?.registerResponseFilter((type, response) => { - if ( - type !== shaka.net.NetworkingEngine.RequestType.SEGMENT || - !response.uri.includes('/api/timedtext') - ) { - return; - } - - const url = new URL(response.uri); - - // Fix positioning for auto-generated subtitles - // Credit to Freetube! - if ( - url.hostname.endsWith('.youtube.com') && - url.pathname === '/api/timedtext' && - url.searchParams.get('caps') === 'asr' && - url.searchParams.get('kind') === 'asr' && - url.searchParams.get('fmt') === 'vtt' - ) { - const stringBody = new TextDecoder().decode(response.data); - // position:0% for LTR text and position:100% for RTL text - const cleaned = stringBody.replaceAll(/ align:start position:(?:10)?0%$/gm, ''); - response.data = new TextEncoder().encode(cleaned).buffer; - } - }); playerElement?.addEventListener('volumechange', saveVolumePreference);