diff --git a/examples/browser/web/index.html b/examples/browser/web/index.html index 6147007c0..50043d41d 100644 --- a/examples/browser/web/index.html +++ b/examples/browser/web/index.html @@ -1,20 +1,30 @@ - - - - - Vite + TS - - -
- - -
- - Library is loading... - + + + + + + YouTube.js Example + + + +
+ + +
+
+
- - - +

+
+
+
+
+ + + + + \ No newline at end of file diff --git a/examples/browser/web/src/main.ts b/examples/browser/web/src/main.ts index e25c0867d..752101578 100644 --- a/examples/browser/web/src/main.ts +++ b/examples/browser/web/src/main.ts @@ -4,13 +4,14 @@ import dashjs from 'dashjs'; async function main() { const yt = await Innertube.create({ + generate_session_locally: true, fetch: async (input: RequestInfo | URL, init?: RequestInit) => { // url const url = typeof input === 'string' ? new URL(input) : input instanceof URL - ? input - : new URL(input.url); + ? input + : new URL(input.url); // transform the url for use with our proxy url.searchParams.set('__host', url.host); @@ -20,8 +21,8 @@ async function main() { const headers = init?.headers ? new Headers(init.headers) : input instanceof Request - ? input.headers - : new Headers(); + ? input.headers + : new Headers(); // now serialize the headers url.searchParams.set('__headers', JSON.stringify([...headers])); @@ -48,29 +49,65 @@ async function main() { cache: new UniversalCache(false), }); - const span = document.getElementById('video_name') as HTMLSpanElement; + const description = document.getElementById('description') as HTMLDivElement; const form = document.querySelector('form') as HTMLFormElement; - - span.textContent = 'Library ready'; + const title = document.getElementById('title') as HTMLHeadingElement; + const metadata = document.getElementById('metadata') as HTMLDivElement; + const loader = document.getElementById('loader') as HTMLDivElement; + const video_container = document.getElementById('video_container') as HTMLDivElement; let player: dashjs.MediaPlayerClass | undefined; form.addEventListener('submit', async (e) => { e.preventDefault(); - span.textContent = 'Loading...'; + if (player) { + player.reset(); + } + + video_container.style.display = 'none'; + loader.style.display = 'block'; + + let video_id; + + const video_id_or_url = document.querySelector('input[type=text]')?.value; - const video_id = document.querySelector( - 'input[type=text]', - )?.value; - if (!video_id) { - span.textContent = 'No video id'; + if (!video_id_or_url) { + title.textContent = 'No video id or URL provided'; return; } + try { + if (video_id_or_url.match(/(http|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])/)) { + const endpoint = await yt.resolveURL(video_id_or_url); + + if (!endpoint.payload.videoId) { + title.textContent = 'Could not resolve URL'; + return; + } + + video_id = endpoint.payload.videoId; + } else { + video_id = video_id_or_url; + } + const video = await yt.getInfo(video_id); - console.log(video); - span.textContent = video.basic_info.title || null; + + loader.style.display = 'none'; + + title.textContent = video.basic_info.title || null; + description.innerHTML = video.secondary_info?.description.toHTML() || ''; + title.textContent = video.basic_info.title || null; + + document.title = video.basic_info.title || ''; + + metadata!.innerHTML = ''; + metadata!.innerHTML += ``; + metadata!.innerHTML += ``; + metadata!.innerHTML += ``; + + video_container.animate({ opacity: [0, 1] }, { duration: 300, easing: 'ease-in-out' }); + video_container.style.display = 'block'; const dash = video.toDash((url) => { url.searchParams.set('__host', url.host); @@ -79,20 +116,23 @@ async function main() { return url; }); - const uri = 'data:application/dash+xml;charset=utf-8;base64,' + - btoa(dash); + const uri = 'data:application/dash+xml;charset=utf-8;base64,' + btoa(dash); // create and append video element const video_element = document.querySelector('video') as HTMLVideoElement; video_element.setAttribute('controls', 'true'); + video_element.poster = video.basic_info.thumbnail![0].url; + // use dash.js to parse the manifest if (player) { player.destroy(); } + player = dashjs.MediaPlayer().create(); player.initialize(video_element, uri, true); + player.setInitialMediaSettingsFor('audio', { lang: 'en-US' }); } catch (error) { - span.textContent = 'An error occurred (see console)'; + title.textContent = 'An error occurred (see console)'; console.error(error); } }); diff --git a/examples/browser/web/src/style.css b/examples/browser/web/src/style.css index 49c2fa060..4d45fb4f7 100644 --- a/examples/browser/web/src/style.css +++ b/examples/browser/web/src/style.css @@ -3,10 +3,87 @@ body { flex-direction: column; align-items: center; font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + background-color: rgb(32, 32, 32); + color: rgb(255, 255, 255); +} + +hr { + height: 1px; + width: 100%; + border: 1px solid transparent; + background-color: rgb(68, 68, 68); +} + +form { + margin: 0.5rem 0; +} + +#loader { + display: none; + border: 10px solid rgb(68, 68, 68); + border-top: 10px solid rgb(255, 255, 255); + border-radius: 50%; + width: 50px; + height: 50px; + align-self: center; + animation: spin 1s linear infinite; + margin: 0.5rem 0; +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} + +#video_container { + display: none; + flex-direction: column; + position: relative; + width: 70vw !important; + margin: 0.5rem 0; +} + +#metadata { + display: flex; + flex-direction: row; + align-self: left; + margin: 0.5rem 0; +} + +#metadata > .metadata_item { + margin: 0 0.3rem; + background-color: beige; + color: black; + font: 1em bold; + padding: 0.2rem 0.5rem; + border-radius: 0.3rem; +} + +#video_container > #description { + align-self: left; + margin-left: 0.5rem; + font-size: medium; } video { - max-width: calc(100vw - 1rem); - width: fit-content; - max-height: calc(90vh - 12rem); + width: 100%; + height: 40vw; +} + +footer { + margin: 0.5rem 0; +} + +@media screen and (max-width: 768px) { + video { + height: auto; + } + #video_container { + width: 100% !important; + } } \ No newline at end of file