i'm trying to use typescript in sveltekit to implement a youtube API. I'm using @types/youtube, hoping that I can get better results getting the video to work by passing the URL and get videoDuration. but so far it's not working.
i was following the template of youtube API, I could get js and videoID version to work but somehow i was having trouble with typescript and passing URL
Any help or experience is appreciated.
<!-- to do: 1) need to handle youtube shorts by replacing short with watch?v= 2) chatbot window on same screen like windows explorer or new page, take some time to reflect --><script lang="ts"> // page function from default app/stores library enables script to get url searchparams from // url import { page } from '$app/stores'; import { onMount, onDestroy } from 'svelte'; let subtitles: {id: string, start: number; end: number; text: string} [] = []; let videoUrl: string = ''; let duration: number = 0; let currentTime: number = 0; let player = new YT.Player("id",{ events: { onReady(event: YT.PlayerEvent) { const targetPlayer: YT.Player = event.target; }, onStateChange(event: YT.OnStateChangeEvent) { const targetPlayer: YT.Player = event.target; const playerData: YT.PlayerState = event.data; } } }); // function to fetch subtitles from cache, database or AI server. async function fetchSubtitles() { subtitles = [ { id: "1", start: 0, end: 5, text: "Hello, welcome to our video." }, { id: "2", start: 6, end: 10, text: "Today, we'll discuss Svelte components." }, { id: "3", start: 11, end: 15, text: "Let's dive right in!" }, { id: "4", start: 16, end: 20, text: "Svelte makes building UIs a breeze." }, ]; } /***************** onMount() ******************/ onMount(() => { // I believe that page should be a reactive var, so query is renewed every time // url changes. But on the other hand, since all vars are reactive, const query = $page.url.searchParams; const encodedUrl = query.get('videoUrl') || ''; //const tag: HTMLScriptElement = document.createElement('script'); // Decode the URL before processing it videoUrl = decodeURIComponent(encodedUrl); // Load the YouTube iframe API script dynamically const tag = document.createElement('script'); tag.src = 'https://www.youtube.com/iframe_api'; document.body.appendChild(tag); // Define a global callback that YouTube API will call once it's ready (window as any).onYouTubeIframeAPIReady = () => { player = new YT.Player("id",{ events: { onReady(event: YT.PlayerEvent) { const targetPlayer: YT.Player = event.target; }, onStateChange(event: YT.OnStateChangeEvent) { const targetPlayer: YT.Player = event.target; const playerData: YT.PlayerState = event.data; } } }) }; // Ensure that the URL is a valid YouTube URL if (videoUrl && !videoUrl.includes("youtube.com") && !videoUrl.includes("youtu.be")) { videoUrl = ''; // Reset if not a valid YouTube URL } //insert iframe api onto DOM //tag.src = "https://www.youtube.com/iframe_api"; //document.body.appendChild(tag); fetchSubtitles(); }); /************* OnMount ****************/ // call eventlistener function when onReady event fire is received by API. player.addEventListener("onReady", (event: YT.PlayerEvent) => { duration = player.getDuration(); currentTime = player.getCurrentTime(); }); /**** // called when the player is ready function onPlayerReady(event): void { duration = player.getDuration(); setInterval((): void => { currentTime = YT.getCurrentTime(); }, 1000); } ***/ //$: duration = player ? player.getDuration() : 0; // Function to construct YouTube URL into embedded form function getEmbedUrl(url: string): string { if (!url) return ''; // Handle short links like youtu.be/xyz const shortLinkMatch = url.match(/youtu\.be\/([^\?]+)/); if (shortLinkMatch) { return `https://www.youtube.com/embed/${shortLinkMatch[1]}`; } // Handle regular YouTube links like youtube.com/watch?v=xyz const regularLinkMatch = url.match(/v=([^&]+)/); if (regularLinkMatch) { return `https://www.youtube.com/embed/${regularLinkMatch[1]}`; } return ''; }</script><main><h1>Watch Video</h1> {#if videoUrl}<div id="id"></div><p> Duration: {duration} seconds </p><p> Current Time: {currentTime} seconds </p> {:else}<p>No valid video URL provided. Please check the link and try again.</p> {/if}</main><style> main { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 2rem; } iframe { margin-top: 1rem; }</style><!-- Watch.svelte page is a parent component to subtitleEditor.svelte component in library. Primary function is to embed youtube video for display, based on the URL that user submitted in the (tentative) main page.svelte apparently it is better to have subtitles fetched from parent component. Then passed assign value to props of SubtitleEditor component. -->