diff --git a/README.md b/README.md
index cd6db460..000ec116 100644
--- a/README.md
+++ b/README.md
@@ -112,7 +112,10 @@ yarn add youtubei.js@latest
npm install github:LuanRT/YouTube.js
```
-**TODO:** Deno install instructions (deno.land)
+When using Deno, you can import YouTube.js directly from deno.land:
+```ts
+import { Innertube } from 'https://deno.land/x/youtubei/deno.ts';
+```
## Usage
Create an InnerTube instance:
@@ -128,8 +131,13 @@ To use YouTube.js in the browser you must proxy requests through your own server
You may provide your own fetch implementation to be used by YouTube.js. Which we will use here to modify and send the requests through our proxy. See [`examples/browser/web`](https://github.com/LuanRT/YouTube.js/tree/main/examples/browser/web) for a simple example using [Vite](https://vitejs.dev/).
```ts
-// Pre-bundled version for the web
-import { Innertube } from 'youtubei.js/bundle/browser';
+// We provide multiple exports for the web.
+// Unbundled ESM version
+import { Innertube } from 'youtubei.js/web';
+// Bundled ESM version
+// import { Innertube } from 'youtubei.js/web.bundle';
+// Production Bundled ESM version
+// import { Innertube } from 'youtubei.js/web.bundle.min';
await Innertube.create({
fetch: async (input: RequestInfo | URL, init?: RequestInit) => {
// Modify the request
@@ -147,7 +155,7 @@ YouTube.js supports streaming of videos in the browser by converting YouTube's s
The example below uses [`dash.js`](https://github.com/Dash-Industry-Forum/dash.js) to play the video.
```ts
-import { Innertube } from 'youtubei.js';
+import { Innertube } from 'youtubei.js/web';
import dashjs from 'dashjs';
const youtube = await Innertube.create({ /* setup - see above */ });
@@ -202,7 +210,7 @@ Our cache uses the `node:fs` module in Node-like environments, `Deno.writeFile`
import { Innertube, UniversalCache } from 'youtubei.js';
// By default, cache stores files in the OS temp directory (or indexedDB in browsers).
const yt = await Innertube.create({
- cache: new UniversalCache()
+ cache: new UniversalCache(false)
});
// You may wish to make the cache persistent (on Node and Deno)
diff --git a/deno/package.json b/deno/package.json
index 14fdfe4b..7485dbc3 100644
--- a/deno/package.json
+++ b/deno/package.json
@@ -1,6 +1,6 @@
{
"name": "youtubei.js",
- "version": "3.0.0",
+ "version": "3.1.0",
"description": "A wrapper around YouTube's private API. Supports YouTube, YouTube Music, YouTube Kids and YouTube Studio (WIP).",
"type": "module",
"types": "./dist/src/platform/lib.d.ts",
diff --git a/deno/src/parser/classes/NavigationEndpoint.ts b/deno/src/parser/classes/NavigationEndpoint.ts
index e26ea202..390051f7 100644
--- a/deno/src/parser/classes/NavigationEndpoint.ts
+++ b/deno/src/parser/classes/NavigationEndpoint.ts
@@ -21,7 +21,6 @@ class NavigationEndpoint extends YTNode {
constructor(data: any) {
super();
- // This is only present in Android nav endpoints
if (Reflect.has(data || {}, 'innertubeCommand'))
data = data.innertubeCommand;
diff --git a/deno/src/parser/classes/PlayerMicroformat.ts b/deno/src/parser/classes/PlayerMicroformat.ts
index 6209b5ec..ae6240dd 100644
--- a/deno/src/parser/classes/PlayerMicroformat.ts
+++ b/deno/src/parser/classes/PlayerMicroformat.ts
@@ -16,7 +16,7 @@ class PlayerMicroformat extends YTNode {
// TODO: check these
width: any;
height: any;
- };
+ } | null;
length_seconds: number;
@@ -42,13 +42,17 @@ class PlayerMicroformat extends YTNode {
this.description = new Text(data.description);
this.thumbnails = Thumbnail.fromResponse(data.thumbnail);
- this.embed = {
- iframe_url: data.embed.iframeUrl,
- flash_url: data.embed.flashUrl,
- flash_secure_url: data.embed.flashSecureUrl,
- width: data.embed.width,
- height: data.embed.height
- };
+ if (data.embed) {
+ this.embed = {
+ iframe_url: data.embed.iframeUrl,
+ flash_url: data.embed.flashUrl,
+ flash_secure_url: data.embed.flashSecureUrl,
+ width: data.embed.width,
+ height: data.embed.height
+ };
+ } else {
+ this.embed = null;
+ }
this.length_seconds = parseInt(data.lengthSeconds);
diff --git a/deno/src/parser/classes/PlaylistVideo.ts b/deno/src/parser/classes/PlaylistVideo.ts
index a33f0dbc..f0dbc179 100644
--- a/deno/src/parser/classes/PlaylistVideo.ts
+++ b/deno/src/parser/classes/PlaylistVideo.ts
@@ -3,6 +3,7 @@ import Parser from '../index.ts';
import Thumbnail from './misc/Thumbnail.ts';
import PlaylistAuthor from './misc/PlaylistAuthor.ts';
import NavigationEndpoint from './NavigationEndpoint.ts';
+import ThumbnailOverlayTimeStatus from './ThumbnailOverlayTimeStatus.ts';
import type Menu from './menus/Menu.ts';
import { YTNode } from '../helpers.ts';
@@ -20,6 +21,7 @@ class PlaylistVideo extends YTNode {
endpoint: NavigationEndpoint;
is_playable: boolean;
menu: Menu | null;
+ upcoming;
duration: {
text: string;
@@ -33,16 +35,30 @@ class PlaylistVideo extends YTNode {
this.title = new Text(data.title);
this.author = new PlaylistAuthor(data.shortBylineText);
this.thumbnails = Thumbnail.fromResponse(data.thumbnail);
- this.thumbnail_overlays = Parser.parse(data.thumbnailOverlays);
+ this.thumbnail_overlays = Parser.parseArray(data.thumbnailOverlays);
this.set_video_id = data?.setVideoId;
this.endpoint = new NavigationEndpoint(data.navigationEndpoint);
this.is_playable = data.isPlayable;
this.menu = Parser.parseItem