Added inline chapter support
This commit is contained in:
@@ -16,15 +16,15 @@
|
||||
sponsorBlockUrl
|
||||
} from '../store';
|
||||
import type { VideoPlay } from './Api/model';
|
||||
import { videoLength, type PhasedDescription } from './misc';
|
||||
|
||||
export let data: { video: VideoPlay };
|
||||
export let data: { video: VideoPlay; content: PhasedDescription };
|
||||
export let currentTime: number = 0;
|
||||
export let audioMode = false;
|
||||
|
||||
let player: MediaPlayerElement;
|
||||
let src: PlayerSrc = [];
|
||||
let categoryBeingSkipped = '';
|
||||
let captions: { label: string; srcLang: string; src: string }[] = [];
|
||||
|
||||
export function seekTo(time: number) {
|
||||
if (typeof player !== 'undefined') {
|
||||
@@ -47,6 +47,30 @@
|
||||
});
|
||||
}
|
||||
|
||||
if (data.content.timestamps) {
|
||||
let chapterWebVTT = 'WEBVTT\n\n';
|
||||
|
||||
let timestampIndex = 0;
|
||||
data.content.timestamps.forEach((timestamp) => {
|
||||
let endTime: string;
|
||||
if (timestampIndex === data.content.timestamps.length - 1) {
|
||||
endTime = videoLength(data.video.lengthSeconds);
|
||||
} else {
|
||||
endTime = data.content.timestamps[timestampIndex + 1].timePretty;
|
||||
}
|
||||
|
||||
chapterWebVTT += `${timestamp.timePretty} --> ${endTime}\n${timestamp.title.replaceAll('-', '').trim()}\n\n`;
|
||||
|
||||
timestampIndex += 1;
|
||||
});
|
||||
|
||||
player.textTracks.add({
|
||||
kind: 'chapters',
|
||||
src: URL.createObjectURL(new Blob([chapterWebVTT])),
|
||||
default: true
|
||||
});
|
||||
}
|
||||
|
||||
player.addEventListener('time-update', () => {
|
||||
currentTime = player.currentTime;
|
||||
});
|
||||
|
||||
@@ -1,18 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import type { Notification, Video, VideoBase } from './Api/model';
|
||||
import { cleanNumber, truncate } from './misc';
|
||||
import { cleanNumber, truncate, videoLength } from './misc';
|
||||
|
||||
export let video: VideoBase | Video | Notification;
|
||||
|
||||
function videoLength(lengthSeconds: number): string {
|
||||
const hours = Math.floor(lengthSeconds / 3600);
|
||||
const minutes = Math.floor((lengthSeconds % 3600) / 60);
|
||||
const seconds = lengthSeconds % 60;
|
||||
|
||||
return `${hours}:${minutes}:${seconds}`;
|
||||
}
|
||||
|
||||
let loading = true;
|
||||
let loaded = false;
|
||||
let failed = false;
|
||||
|
||||
@@ -13,9 +13,23 @@ export function cleanNumber(number: number): string {
|
||||
return humanNumber(number, (number: number) => Number.parseFloat(number.toString()).toFixed(1));
|
||||
}
|
||||
|
||||
export function phaseDescription(content: string): {
|
||||
export function videoLength(lengthSeconds: number): string {
|
||||
const hours = Math.floor(lengthSeconds / 3600);
|
||||
const minutes = Math.floor((lengthSeconds % 3600) / 60);
|
||||
const seconds = lengthSeconds % 60;
|
||||
|
||||
if (hours !== 0) {
|
||||
return `${hours}:${minutes}:${seconds}`;
|
||||
} else {
|
||||
return `${minutes}:${seconds}`;
|
||||
}
|
||||
}
|
||||
|
||||
export interface PhasedDescription {
|
||||
description: string, timestamps: { title: string; time: number; timePretty: string; }[];
|
||||
} {
|
||||
}
|
||||
|
||||
export function phaseDescription(content: string): PhasedDescription {
|
||||
const timestamps: { title: string; time: number; timePretty: string; }[] = [];
|
||||
const lines = content.split('\n');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user