diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js
index 809e808..049d522 100644
--- a/docs/.vuepress/config.js
+++ b/docs/.vuepress/config.js
@@ -9,7 +9,18 @@ import { prismjsPlugin } from '@vuepress/plugin-prismjs';
const __dirname = getDirname(import.meta.url)
export default defineUserConfig({
- lang: 'en-US',
+ locales: {
+ '/': {
+ lang: 'en-US',
+ title: 'YouTube.js',
+ description: 'A JavaScript client for YouTube\'s private API, known as InnerTube.',
+ },
+ '/zh/': {
+ lang: 'zh-CN',
+ title: 'YouTube.js',
+ description: 'YouTube 私有 API(InnerTube)的 JavaScript 客户端',
+ },
+ },
head: [
['link', { rel: 'icon', href: '/images/favicon/favicon-32x32.png' }],
['link', { rel: 'icon', href: '/images/favicon/favicon-16x16.png' }],
@@ -25,8 +36,6 @@ export default defineUserConfig({
['meta', { property: 'og:locale', content: 'en_US' }],
['meta', { property: 'og:image', content: '/images/logo.png' }],
],
- title: 'YouTube.js',
- description: 'A JavaScript client for YouTube\'s private API, known as InnerTube.',
clientConfigFile: path.resolve(__dirname, 'client.js'),
theme: defaultTheme({
docsRepo: 'https://github.com/LuanRT/ytjs-docs',
@@ -34,71 +43,145 @@ export default defineUserConfig({
docsDir: 'docs',
contributors: false,
repo: 'https://github.com/LuanRT/YouTube.js',
- navbar: [
- {
- text: 'Guide',
- link: '/guide/'
- },
- {
- text: 'Discord',
- link: 'https://discord.gg/syDu7Yks54'
- },
- {
- text: '❤️ Sponsor',
- link: 'https://github.com/sponsors/LuanRT',
- },
- ],
- colorModeSwitch: true,
- sidebar: {
- '/guide/': [
- {
- title: 'Guide',
- collapsable: false,
- children: [
- {
- link: '/guide/',
- text: 'Introduction'
- },
- {
- link: '/guide/getting-started',
- text: 'Getting Started'
- },
- {
- link: '/guide/browser-usage',
- text: 'Browser Usage'
- },
- {
- link: '/guide/caching',
- text: 'Caching'
- },
+ locales: {
+ '/': {
+ selectLanguageName: 'English',
+ editLinkText: 'Edit this page',
+ navbar: [
+ {
+ text: 'Guide',
+ link: '/guide/'
+ },
+ {
+ text: 'Discord',
+ link: 'https://discord.gg/syDu7Yks54'
+ },
+ {
+ text: '❤️ Sponsor',
+ link: 'https://github.com/sponsors/LuanRT',
+ },
+ ],
+ sidebar: {
+ '/guide/': [
{
- link: '/guide/proxies',
- text: 'Proxies'
- },
- {
- link: '/guide/authentication',
- text: 'Authentication'
- },
- {
- link: '/guide/advanced-usage',
- text: 'Advanced Usage'
- },
- {
- link: '/guide/troubleshooting',
- text: 'Troubleshooting'
- },
+ title: 'Guide',
+ collapsable: false,
+ children: [
+ {
+ link: '/guide/',
+ text: 'Introduction'
+ },
+ {
+ link: '/guide/getting-started',
+ text: 'Getting Started'
+ },
+ {
+ link: '/guide/browser-usage',
+ text: 'Browser Usage'
+ },
+ {
+ link: '/guide/caching',
+ text: 'Caching'
+ },
+ {
+ link: '/guide/proxies',
+ text: 'Proxies'
+ },
+ {
+ link: '/guide/authentication',
+ text: 'Authentication'
+ },
+ {
+ link: '/guide/advanced-usage',
+ text: 'Advanced Usage'
+ },
+ {
+ link: '/guide/troubleshooting',
+ text: 'Troubleshooting'
+ },
+ {
+ link: '/guide/faq',
+ text: 'FAQ'
+ },
+ ]
+ }
+ ],
+ '/api/': [
+ ],
+ '/googlevideo/': [
+ ]
+ }
+ },
+ '/zh/': {
+ selectLanguageName: '简体中文',
+ editLinkText: '编辑此页',
+ navbar: [
+ {
+ text: '指南',
+ link: '/zh/guide/'
+ },
+ {
+ text: 'Discord',
+ link: 'https://discord.gg/syDu7Yks54'
+ },
+ {
+ text: '❤️ 赞助',
+ link: 'https://github.com/sponsors/LuanRT',
+ },
+ ],
+ sidebar: {
+ '/zh/guide/': [
{
- link: '/guide/faq',
- text: 'FAQ'
- },
+ title: '指南',
+ collapsable: false,
+ children: [
+ {
+ link: '/zh/guide/',
+ text: '介绍'
+ },
+ {
+ link: '/zh/guide/getting-started',
+ text: '快速开始'
+ },
+ {
+ link: '/zh/guide/browser-usage',
+ text: '浏览器使用'
+ },
+ {
+ link: '/zh/guide/caching',
+ text: '缓存'
+ },
+ {
+ link: '/zh/guide/proxies',
+ text: '代理'
+ },
+ {
+ link: '/zh/guide/authentication',
+ text: '身份验证'
+ },
+ {
+ link: '/zh/guide/advanced-usage',
+ text: '高级用法'
+ },
+ {
+ link: '/zh/guide/troubleshooting',
+ text: '故障排除'
+ },
+ {
+ link: '/zh/guide/faq',
+ text: '常见问题'
+ },
+ ]
+ }
+ ],
+ '/zh/api/': [
+ ],
+ '/zh/googlevideo/': [
]
}
- ],
- '/api/': [
- ],
- '/googlevideo/': [
- ]
- }
+ }
+ },
+ colorModeSwitch: true,
}),
plugins: [
prismjsPlugin({
@@ -113,6 +196,9 @@ export default defineUserConfig({
'/': {
placeholder: 'Search',
},
+ '/zh/': {
+ placeholder: '搜索',
+ },
},
}),
],
diff --git a/docs/zh/README.md b/docs/zh/README.md
new file mode 100644
index 0000000..ff07fde
--- /dev/null
+++ b/docs/zh/README.md
@@ -0,0 +1,84 @@
+---
+home: true
+title: 首页
+heroText: YouTube.js
+heroImage: '/images/logo.png'
+tagline: YouTube 私有 API 的 JavaScript 客户端
+actions:
+ - text: 快速开始 →
+ link: /zh/guide/
+ type: primary
+ - text: API 文档
+ link: /zh/api/
+ type: secondary
+features:
+ - title: 🚀 强大且灵活
+ details: 无限制访问 YouTube 数据。从简单搜索到复杂操作,应有尽有。
+ - title: 🛡️ 无需 API 密钥
+ details: 无需 API 密钥或配额限制。像 YouTube 网站一样使用私有 API。
+ - title: 🔌 平台无关
+ details: 兼容 Node.js、Deno 和现代浏览器。在任何 JavaScript 运行环境中使用。
+footer: MIT 许可证 | 版权所有 © LuanRT
+---
+
+## 生态系统
+
+
+
+
GoogleVideo
+
用于处理 YouTube 专有视频流协议(UMP/SABR)的模块集合。
+
查看文档 →
+
+
+
+
扩展
+
为 YouTube.js 添加额外功能,满足特定使用场景。
+
了解更多 →
+
+
+
+
diff --git a/docs/zh/api/README.md b/docs/zh/api/README.md
new file mode 100644
index 0000000..1af4526
--- /dev/null
+++ b/docs/zh/api/README.md
@@ -0,0 +1,30 @@
+# API 文档
+
+API 技术文档主要包含代码、类型定义和接口说明,这些内容使用英文是开发者的标准实践。
+
+为了保持文档的准确性和及时性,API 参考文档暂未提供中文翻译。
+
+**请切换到英文版查看完整的 API 文档:**
+
+👉 [查看英文 API 文档](/api/)
+
+---
+
+## 快速链接
+
+- [Innertube 类](/api/classes/Innertube.md) - 主要的客户端类
+- [Actions 类](/api/classes/Actions.md) - 执行 InnerTube 操作
+- [Session 类](/api/classes/Session.md) - 会话管理
+- [Parser 命名空间](/api/youtubei.js/namespaces/Parser/README.md) - 响应解析器
+- [YTNodes 命名空间](/api/youtubei.js/namespaces/YTNodes/README.md) - YouTube 节点类型
+
+## 主要命名空间
+
+- [YT](/api/youtubei.js/namespaces/YT/README.md) - YouTube 相关类型
+- [YTMusic](/api/youtubei.js/namespaces/YTMusic/README.md) - YouTube Music 相关类型
+- [YTKids](/api/youtubei.js/namespaces/YTKids/README.md) - YouTube Kids 相关类型
+- [YTShorts](/api/youtubei.js/namespaces/YTShorts/README.md) - YouTube Shorts 相关类型
+
+---
+
+如有疑问,请参考[指南部分](/zh/guide/)或加入我们的 [Discord 社区](https://discord.gg/syDu7Yks54)。
diff --git a/docs/zh/googlevideo/README.md b/docs/zh/googlevideo/README.md
new file mode 100644
index 0000000..383de59
--- /dev/null
+++ b/docs/zh/googlevideo/README.md
@@ -0,0 +1,118 @@
+# GoogleVideo
+
+用于处理 YouTube 专有视频流协议(UMP/SABR)的模块集合。可用于构建客户端或与现有媒体播放器集成(例如 [Shaka Player](https://shaka-player-demo.appspot.com/docs/api/index.html))。
+
+[API 参考 →](/googlevideo/api/)
+
+[代码仓库](https://github.com/LuanRT/googlevideo)
+
+## 安装
+
+```bash
+# NPM
+npm install googlevideo
+
+# JSR / Deno
+npx jsr add @luanrt/googlevideo
+deno add jsr:@luanrt/googlevideo
+
+# GitHub
+npm install LuanRT/googlevideo
+```
+
+## 基本用法
+
+以下是使用 UMP 模块创建缓冲区、写入部分并处理它们的基本示例:
+
+```typescript
+import { CompositeBuffer, UmpReader, UmpWriter } from 'googlevideo/ump';
+import { MediaHeader, UMPPartId } from 'googlevideo/protos';
+import { concatenateChunks } from 'googlevideo/utils';
+import { Part } from 'googlevideo/shared-types';
+
+function handleMediaHeader(part: Part) {
+ const mediaHeader = MediaHeader.decode(concatenateChunks(part.data.chunks));
+ console.log('Media Header:', mediaHeader);
+}
+
+function handleMedia(part: Part) {
+ const headerId = part.data.getUint8(0);
+ console.log(`Media Part (Associated Header ID: ${headerId}):`, part.data.split(1).remainingBuffer.getLength(), 'bytes');
+}
+
+function handleMediaEnd(part: Part) {
+ const headerId = part.data.getUint8(0);
+ console.log(`Media End Part (Associated Header ID: ${headerId}):`, part.data.split(1).remainingBuffer.getLength(), 'bytes');
+}
+
+const umpPartHandlers = new Map void>([
+ [ UMPPartId.MEDIA_HEADER, handleMediaHeader ],
+ [ UMPPartId.MEDIA, handleMedia ],
+ [ UMPPartId.MEDIA_END, handleMediaEnd ]
+]);
+
+const buffer = mockUmpData();
+const reader = new UmpReader(buffer);
+
+reader.read((part) => {
+ const handler = umpPartHandlers.get(part.type);
+ if (handler) {
+ handler(part);
+ } else {
+ console.warn(`No handler for part type: ${part.type}`);
+ }
+});
+
+/**
+ * 生成包含 MEDIA_HEADER 以及相应的 MEDIA 和 MEDIA_END 部分的模拟 UMP 数据缓冲区。
+ * 此组表示单个音频段,这是你在真实 UMP 流中通常会看到的内容。
+ */
+function mockUmpData(): CompositeBuffer {
+ const buffer = new CompositeBuffer();
+ const writer = new UmpWriter(buffer);
+
+ const audioHeaderId = 0;
+
+ const partsToWrite: [UMPPartId, Uint8Array][] = [
+ [
+ UMPPartId.MEDIA_HEADER,
+ MediaHeader.encode({
+ headerId: audioHeaderId,
+ videoId: "sOa4VVlI9tE",
+ itag: 141,
+ lmt: 1645502668395260,
+ xtags: "",
+ startRange: 5463800,
+ isInitSeg: false,
+ sequenceNumber: 0,
+ durationMs: 0,
+ formatId: {
+ itag: 141,
+ lastModified: 1645502668395260,
+ xtags: ""
+ },
+ contentLength: 963966,
+ }).finish()
+ ],
+ [ UMPPartId.MEDIA, new Uint8Array([ audioHeaderId, ...new Uint8Array(827609).fill(0) ]) ],
+ [ UMPPartId.MEDIA, new Uint8Array([ audioHeaderId, ...new Uint8Array(136357).fill(0) ]) ],
+ [ UMPPartId.MEDIA_END, new Uint8Array([ audioHeaderId ]) ]
+ ];
+
+ for (const [type, data] of partsToWrite) {
+ writer.write(type, data);
+ }
+
+ return buffer;
+}
+```
+
+预期输出:
+```
+Media Header: { ... }
+Media Part (Associated Header ID: 0): 827609 bytes
+Media Part (Associated Header ID: 0): 136357 bytes
+Media End Part (Associated Header ID: 0): 0 bytes
+```
+
+> 更多高级用法示例可以在 [examples](https://github.com/LuanRT/googlevideo/tree/main/examples) 目录中找到。
diff --git a/docs/zh/guide/README.md b/docs/zh/guide/README.md
new file mode 100644
index 0000000..6769a65
--- /dev/null
+++ b/docs/zh/guide/README.md
@@ -0,0 +1,7 @@
+# 介绍
+
+YouTube.js 是 YouTube 私有 API(称为 "InnerTube")的 JavaScript 客户端。它允许你以编程方式与 YouTube 交互,提供对视频、评论、直播聊天、流媒体数据等的访问。支持 Node.js、Deno、浏览器以及任何其他现代 JavaScript 环境。
+
+[Discord](https://discord.gg/syDu7Yks54) | [GitHub](https://github.com/LuanRT/YouTube.js) | [NPM](https://www.npmjs.com/package/youtubei.js)
+
+**免责声明**:本库与 YouTube 或 Google 无关联。
diff --git a/docs/zh/guide/advanced-usage.md b/docs/zh/guide/advanced-usage.md
new file mode 100644
index 0000000..c270a4d
--- /dev/null
+++ b/docs/zh/guide/advanced-usage.md
@@ -0,0 +1,79 @@
+## 扩展库
+
+YouTube.js 是模块化的,易于扩展。内部使用的大多数方法、类和实用程序都是公开的,可以用来实现你自己的扩展,而无需修改库的源代码。
+
+例如,假设我们想实现一个检索视频信息的方法。我们可以使用 `Actions` 类的实例来做到这一点:
+```ts
+import { Innertube, UniversalCache } from 'youtubei.js';
+
+const yt = await Innertube.create({ cache: new UniversalCache(true) });
+
+async function getVideoInfo(videoId: string) {
+ const videoInfo = await yt.actions.execute('/player', {
+ // 你可以在这里添加任何额外的负载,它们将与发送到 InnerTube 的默认负载合并。
+ videoId,
+ client: 'YTMUSIC', // 要使用的 InnerTube 客户端。
+ parse: true // 告诉 YouTube.js 解析响应(不发送到 InnerTube)。
+ });
+
+ return videoInfo;
+}
+
+const videoInfo = await getVideoInfo('jLTOuvBTLxA');
+console.info(videoInfo);
+```
+
+或者,假设我们在解析的响应中找到一个 `NavigationEndpoint`(例如,一个按钮)。我们可以像这样轻松调用它:
+```ts
+import { Innertube, UniversalCache, YTNodes } from 'youtubei.js';
+
+const yt = await Innertube.create({ cache: new UniversalCache(true) });
+
+const artist = await yt.music.getArtist('UC52ZqHVQz5OoGhvbWiRal6g');
+const albums = artist.sections[1].as(YTNodes.MusicCarouselShelf);
+
+// 假设我们想点击"更多"按钮:
+const button = albums.as(YTNodes.MusicCarouselShelf).header?.more_content;
+
+if (button) {
+ // 确保它存在后,我们可以使用以下代码调用其导航端点:
+ const page = await button.endpoint.call(yt.actions, { parse: true });
+ console.info(page);
+}
+```
+
+## 使用解析器
+
+YouTube.js 的解析器使你能够解析 InnerTube 响应并将其节点转换为易于操作的强类型对象。此外,它还提供了许多实用方法。
+
+这是一个例子:
+```ts
+// 参见 ./examples/parser
+
+import { Parser, YTNodes } from 'youtubei.js';
+import { readFileSync } from 'fs';
+
+// YouTube Music 的艺术家页面响应
+const data = readFileSync('./artist.json').toString();
+
+const page = Parser.parseResponse(JSON.parse(data));
+
+const header = page.header?.item().as(YTNodes.MusicImmersiveHeader, YTNodes.MusicVisualHeader);
+
+console.info('Header:', header);
+
+// 解析器使用代理对象为处理 InnerTube 的数据数组添加类型安全和实用方法:
+const tab = page.contents?.item().as(YTNodes.SingleColumnBrowseResults).tabs.firstOfType(YTNodes.Tab);
+
+if (!tab)
+ throw new Error('未找到目标选项卡');
+
+if (!tab.content)
+ throw new Error('目标选项卡似乎为空');
+
+const sections = tab.content?.as(YTNodes.SectionList).contents.as(YTNodes.MusicCarouselShelf, YTNodes.MusicDescriptionShelf, YTNodes.MusicShelf);
+
+console.info('Sections:', sections);
+```
+
+解析器的文档可以在[这里](https://github.com/LuanRT/YouTube.js/blob/main/src/parser)找到。
diff --git a/docs/zh/guide/authentication.md b/docs/zh/guide/authentication.md
new file mode 100644
index 0000000..4a00068
--- /dev/null
+++ b/docs/zh/guide/authentication.md
@@ -0,0 +1,67 @@
+# 身份验证
+
+## Cookies
+
+这是大多数基于 Web 的客户端类型向 YouTube 进行身份验证的推荐方式:
+
+```js
+const innertube = await Innertube.create({
+ cookie: '...'
+});
+```
+
+获取你的 cookies:
+1. 在浏览器中打开一个新的无痕/隐私窗口(这可以防止你的 cookies 被轮换)
+2. 在无痕窗口中登录 YouTube
+3. 打开开发者工具(F12)
+4. 转到网络(Network)选项卡
+5. 从任何对 `youtube.com` 的请求中复制 `Cookie` 标头的值
+6. 复制 cookies 后关闭无痕窗口
+
+## YouTube TV OAuth2(受限)
+
+**重要提示:** 由于 Google 所做的更改,OAuth2 身份验证现在仅适用于 TV InnerTube 客户端。对于其他客户端类型,请使用基于 cookie 的身份验证(请参阅上面的 Cookies 部分)。
+
+智能电视的 YouTube 应用使用 OAuth2 进行身份验证,由于它也使用 InnerTube,我们可以使用其客户端 ID 和客户端密钥检索有效令牌。
+
+```ts
+innertube.session.on('auth-pending', (data) => {
+ // data.verification_url 包含授权 URL。
+ // data.user_code 包含要在网站上输入的代码。
+});
+
+innertube.session.on('auth', ({ credentials }) => {
+ // 对凭据执行某些操作,例如将它们保存到文件。
+ console.log('登录成功');
+});
+
+// 当访问令牌过期时触发。
+innertube.session.on('update-credentials', ({ credentials }) => { /** 对更新的凭据执行某些操作。 */ });
+
+await innertube.session.signIn(/* 凭据 */);
+```
+
+可以在[这里](https://github.com/LuanRT/YouTube.js/blob/main/examples/auth/yttv-oauth2.js)找到示例。
+
+### 缓存
+
+如果你不想每次初始化会话时都启动登录流程,可以缓存凭据。请注意,这不是推荐的做法,因为可能会导致安全问题。
+
+```js
+// 如果使用此方法,下次调用 signIn 不会触发 'auth-pending',而只会触发 'auth'
+await innertube.session.oauth.cacheCredentials();
+```
+
+**注意:** 使用缓存的凭据时,仍然需要调用 `Session#signIn()`。
+
+### 撤销凭据
+
+注销方法可用于撤销和删除当前会话的凭据。
+
+```js
+await innertube.session.signOut();
+
+// 如果你不想注销当前会话
+// 只想删除缓存的凭据,请使用:
+await innertube.session.oauth.removeCache();
+```
diff --git a/docs/zh/guide/browser-usage.md b/docs/zh/guide/browser-usage.md
new file mode 100644
index 0000000..88ee47d
--- /dev/null
+++ b/docs/zh/guide/browser-usage.md
@@ -0,0 +1,52 @@
+::: warning
+此示例已过时。请查看 [kira](https://github.com/LuanRT/kira) 或 [sabr-shaka-example](https://github.com/LuanRT/googlevideo/tree/main/examples/sabr-shaka-example) 以获取最新的浏览器使用方法。
+:::
+
+# 浏览器使用
+要在浏览器中使用 YouTube.js,你必须通过自己的服务器代理请求。Deno 中的简单代理实现可在 [`examples/browser/proxy/deno.ts`](https://github.com/LuanRT/YouTube.js/tree/main/examples/browser/proxy/deno.ts) 找到。
+
+你可以提供自己的 fetch 实现供 YouTube.js 使用,我们将使用它来修改请求并通过代理发送。有关使用 [Vite](https://vitejs.dev/) 的简单示例,请参阅 [`examples/browser/web`](https://github.com/LuanRT/YouTube.js/tree/main/examples/browser/web)。
+
+
+```ts
+import { Innertube } from 'youtubei.js/web';
+await Innertube.create({
+ fetch: async (input: RequestInfo | URL, init?: RequestInit) => {
+ // 修改请求
+ // 并将其发送到代理
+
+ return fetch(request, init);
+ }
+});
+```
+
+### 流媒体
+YouTube.js 支持在浏览器中通过将 YouTube 的流媒体数据转换为 MPEG-DASH 清单来播放视频。
+
+下面的示例使用 [`dash.js`](https://github.com/Dash-Industry-Forum/dash.js) 来播放视频。
+
+```ts
+import { Innertube } from 'youtubei.js/web';
+import dashjs from 'dashjs';
+
+const innertube = await Innertube.create({ /* 设置 - 见上文 */ });
+
+// 获取视频信息
+const videoInfo = await innertube.getInfo('videoId', { client: 'TV' });
+
+// 现在转换为 dash 清单
+// 再次强调 - 要能够在浏览器中播放视频 - 你必须通过自己的服务器代理请求
+// 为此,我们提供了一个方法来在将 URL 写入清单之前转换它们
+const manifest = await videoInfo.toDash(url => {
+ // 修改 url
+ // 并返回它
+ return url;
+});
+
+const uri = "data:application/dash+xml;charset=utf-8;base64," + btoa(manifest);
+
+const videoElement = document.getElementById('video_player');
+
+const player = dashjs.MediaPlayer().create();
+player.initialize(videoElement, uri, true);
+```
diff --git a/docs/zh/guide/caching.md b/docs/zh/guide/caching.md
new file mode 100644
index 0000000..b945217
--- /dev/null
+++ b/docs/zh/guide/caching.md
@@ -0,0 +1,24 @@
+# 缓存
+缓存转换后的播放器和会话实例可以大大提高性能。我们的 `UniversalCache` 实现根据环境使用不同的缓存方法。
+
+在 Node.js 中,我们使用 `node:fs` 模块,在 Deno 中使用 `Deno.writeFile()`,在浏览器中使用 `indexedDB`。
+
+默认情况下,缓存将数据存储在操作系统的临时目录中(或浏览器中的 `indexedDB`)。
+
+下面的示例创建一个非持久缓存。
+```ts
+import { Innertube, UniversalCache } from 'youtubei.js';
+const innertube = await Innertube.create({ cache: new UniversalCache(false) });
+```
+
+你可以通过指定缓存目录的路径使其持久化,如果目录不存在将会创建。
+```ts
+const innertube = await Innertube.create({
+ cache: new UniversalCache(
+ // 启用持久缓存
+ true,
+ // 缓存目录的路径。如果目录不存在将会创建
+ './.cache'
+ )
+});
+```
diff --git a/docs/zh/guide/faq.md b/docs/zh/guide/faq.md
new file mode 100644
index 0000000..2d675c8
--- /dev/null
+++ b/docs/zh/guide/faq.md
@@ -0,0 +1,23 @@
+# 常见问题
+
+## 什么是 "InnerTube"?
+
+InnerTube 是 YouTube 的私有 API。官方 YouTube 网站和应用程序使用它来获取数据。
+
+[How Project InnerTube Helped Pull YouTube Out of the Gutter](https://gizmodo.com/how-project-innertube-helped-pull-youtube-out-of-the-gu-1704946491);
+
+## 是否支持身份验证?
+
+是的,请参阅[身份验证](./authentication.md)指南。
+
+## 如何禁用日志记录?
+
+你可以通过更改默认日志级别来禁用日志记录。更多信息可以在[故障排除](./troubleshooting.md)页面找到。
+
+## 支持哪些环境?
+
+支持 Node.js、Deno、现代浏览器和 React Native。
+
+## 为什么视频信息请求在我的服务器上失败?
+
+失败的原因有很多。最常见的原因是服务器的 IP 地址被 YouTube 封锁。不幸的是,目前没有已知的解决方案。
diff --git a/docs/zh/guide/getting-started.md b/docs/zh/guide/getting-started.md
new file mode 100644
index 0000000..69c8f66
--- /dev/null
+++ b/docs/zh/guide/getting-started.md
@@ -0,0 +1,144 @@
+# 快速开始
+
+## 前置要求
+YouTube.js 可在 Node.js、Deno 和现代浏览器上运行。
+
+它需要具有以下特性的运行时:
+- [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
+ - 在 Node 上,我们使用 [undici](https://github.com/nodejs/undici) 的 fetch 实现,需要 Node.js 16.8+。如果需要使用更旧的版本,可以提供自己的 fetch 实现。详见[提供自定义 fetch 实现](#custom-fetch)。
+ - fetch 返回的 `Response` 对象必须符合规范,如果要使用 `VideoInfo#download` 方法,必须返回 `ReadableStream` 对象。(像 `node-fetch` 这样的实现返回非标准的 `Readable` 对象。)
+- 需要 [`EventTarget`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget) 和 [`CustomEvent`](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent)。
+
+
+## 安装
+```bash
+# NPM
+npm install youtubei.js@latest
+
+# Yarn
+yarn add youtubei.js@latest
+
+# Git(最新版本)
+npm install github:LuanRT/YouTube.js
+
+# Deno
+deno add npm:youtubei.js@latest
+```
+
+Deno(已弃用):
+```ts
+import { Innertube } from 'https://deno.land/x/youtubei/deno.ts';
+```
+
+## 基本用法
+```ts
+import { Innertube } from 'youtubei.js';
+const innertube = await Innertube.create(/* 选项 */);
+```
+
+### 配置选项
+
+#### `lang` (string)
+- **描述**:会话语言。
+- **默认值**:`en`
+
+#### `location` (string)
+- **描述**:地理位置设置。
+- **默认值**:`US`
+
+#### `user_agent` (string)
+- **描述**:InnerTube 请求的用户代理。
+- **默认值**:`undefined`
+
+#### `account_index` (number)
+- **描述**:要使用的账户索引。如果有多个账户登录,这很有用。仅适用于 cookies。
+- **默认值**:`0`
+
+#### `on_behalf_of_user` (string)
+- **描述**:要使用的 YouTube 个人资料/频道的页面 ID,如果登录账户有多个个人资料。
+- **默认值**:`undefined`
+
+#### `visitor_data` (string)
+- **描述**:持久访客数据字符串,允许 YouTube 即使在未登录时也能提供定制内容。
+- **默认值**:`undefined`
+
+#### `po_token` (string)
+- **描述**:会话绑定的原始证明令牌(认证令牌),用于确认请求来自真实客户端。
+- **默认值**:`undefined`
+
+#### `player_id` (string)
+- **描述**:播放器 ID 覆盖。可用于在 YouTube 引入破坏性更改时通过强制使用旧播放器来解决临时问题。
+- **默认值**:`undefined`
+
+#### `retrieve_player` (boolean)
+- **描述**:指定是否检索 JS 播放器。禁用此选项将使会话创建更快,但无法解密格式。
+- **默认值**:`true`
+
+#### `enable_safety_mode` (boolean)
+- **描述**:启用 YouTube 的安全模式,防止加载潜在不安全的内容。
+- **默认值**:`false`
+
+#### `retrieve_innertube_config` (boolean)
+- **描述**:指定是否检索 InnerTube 配置。对 "onesie" 请求有用。
+- **默认值**:`true`
+
+#### `generate_session_locally` (boolean)
+- **描述**:在本地生成会话数据而不是从 YouTube 检索,以获得更好的性能。如果会话已缓存,则忽略此选项。
+- **默认值**:`false`
+
+#### `enable_session_cache` (boolean)
+- **描述**:缓存会话数据以供将来使用。
+- **默认值**:`true`
+
+#### `device_category` (string)
+- **描述**:会话的平台类型(`DESKTOP`、`MOBILE` 等)。
+- **默认值**:`DESKTOP`
+
+#### `client_type` (string)
+- **描述**:InnerTube 客户端类型(`WEB`、`ANDROID` 等)。
+- **默认值**:`WEB`
+
+#### `timezone` (string)
+- **描述**:会话的时区。
+- **默认值**:`*`
+
+#### `cache` (ICache)
+- **描述**:缓存实现。
+- **默认值**:`undefined`
+
+#### `cookie` (string)
+- **描述**:用于身份验证会话的 Cookies。
+- **默认值**:`undefined`
+
+#### `fetch` (FetchFunction)
+- **描述**:自定义 fetch 实现。
+- **默认值**:`fetch`
+
+## 提供自定义 JavaScript 解释器
+
+某些功能(如解密流媒体 URL)需要执行 YouTube 的混淆 JavaScript 代码。YouTube.js **不**包含用于此目的的内置解释器,因此你必须提供自己的解释器。
+
+以下是使用 JavaScript 的 `Function` 构造函数的示例:
+
+```ts
+import { Innertube, Platform, Types } from 'youtubei.js/web';
+
+Platform.shim.eval = async (data: Types.BuildScriptResult, env: Record) => {
+ const properties = [];
+
+ if(env.n) {
+ properties.push(`n: exportedVars.nFunction("${env.n}")`)
+ }
+
+ if (env.sig) {
+ properties.push(`sig: exportedVars.sigFunction("${env.sig}")`)
+ }
+
+ const code = `${data.output}\nreturn { ${properties.join(', ')} }`;
+
+ return new Function(code)();
+}
+
+const innertube = await Innertube.create(/* 选项 */);
+// ...
+```
diff --git a/docs/zh/guide/proxies.md b/docs/zh/guide/proxies.md
new file mode 100644
index 0000000..1f7e499
--- /dev/null
+++ b/docs/zh/guide/proxies.md
@@ -0,0 +1,14 @@
+# 代理
+你可以提供自己的 fetch 实现供 YouTube.js 使用。这在某些情况下很有用,可以在发送请求之前修改它们,并在返回响应之前转换它们(例如用于代理)。
+```ts
+// 提供 fetch 实现
+const yt = await Innertube.create({
+ fetch: async (input: RequestInfo | URL, init?: RequestInit) => {
+ // 使用你自己的 fetch 实现发起请求
+ // 并返回响应
+ return new Response(
+ /* ... */
+ );
+ }
+});
+```
diff --git a/docs/zh/guide/troubleshooting.md b/docs/zh/guide/troubleshooting.md
new file mode 100644
index 0000000..cb82563
--- /dev/null
+++ b/docs/zh/guide/troubleshooting.md
@@ -0,0 +1,9 @@
+# 故障排除
+
+## 更改日志级别
+
+```typescript
+import { Log } from 'youtubei.js';
+// 可用级别:NONE, ERROR, WARNING, INFO, DEBUG
+Log.setLevel(Log.Level.NONE);
+```