diff --git a/README.md b/README.md index a138916..4090204 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,35 @@ -## 简介 +[中文](README.zh.md) -liveship 是一个小巧易用的直播录制工具,目前已支持抖音、虎牙、小红书、tiktok、twitch,未来计划添加更多平台支持。 +## Introduction -## 工作原理 +liveship is a compact and easy-to-use live streaming recording tool. It currently supports YouTube, TikTok, Twitch, Douyin, Huya, and Xiaohongshu, with plans to add support for more platforms in the future. -liveship 本质上只是 ffmpeg 套壳,通过模拟请求获取直播流地址,然后使用 ffmpeg 进行录制。因此要求您的电脑上必须安装有 ffmpeg,并在“程序设置”页面指定 ffmpeg 路径。 +## How It Works -## 技术栈 +liveship essentially acts as a wrapper for ffmpeg. It simulates requests to obtain live stream URLs and then uses ffmpeg to record them. Therefore, you must have ffmpeg installed on your computer and specify the path to ffmpeg on the "Program Settings" page. -自豪的使用 rust、tauri 和 svelte 5 构建。 +## Tech Stack -## 使用方法 +Proudly built with Rust, Tauri, and Svelte 5. -liveship 是一个基于 tauri 的桌面应用程序,您可以从 [release](https://github.com/jlvihv/liveship/releases/) 页面下载对应平台的二进制文件,然后安装运行。 +## Usage -## 常见问题 +liveship is a Tauri-based desktop application. You can download the binary files for your platform from the [release](https://github.com/jlvihv/liveship/releases/) page, then install and run it. -1. mac os 提示“文件已损坏,无法打开”:这是因为 mac os 限制了非 app store 的应用程序,您可以在终端中执行 `sudo xattr -d com.apple.quarantine /Applications/liveship.app` 命令解除限制。 +## FAQ -## 特别鸣谢 +1. macOS prompts "The file is damaged and cannot be opened": This is because macOS restricts applications not from the App Store. You can remove the restriction by running the command `sudo xattr -d com.apple.quarantine /Applications/liveship.app` in the terminal. -直播源解析的代码很大程度上参考了 [DouyinLiveRecorder](https://github.com/ihmily/DouyinLiveRecorder) 项目,在此致以诚挚的感谢。 +## Special Thanks -## 特别说明 +The code for live stream parsing largely references the [DouyinLiveRecorder](https://github.com/ihmily/DouyinLiveRecorder) project. We extend our sincere thanks for their work. -liveship 计划在 1.0 版本之后添加收费功能,作为我独立开发人生道路的探索。但在 1.0 之前,所有功能都是开源免费的,期待您的建议和反馈。 +## Special Note + +liveship plans to introduce paid features after version 1.0 as part of my journey as an independent developer. However, all features will be open-source and free before version 1.0. Your suggestions and feedback are highly appreciated. ## License CC BY-NC (Creative Commons Attribution-NonCommercial): -允许复制、发行、展示和表演作品及其衍生作品,但仅限于非商业用途。 +Allows copying, distribution, display, and performance of the work and its derivative works, but only for non-commercial purposes. diff --git a/README.zh.md b/README.zh.md new file mode 100644 index 0000000..8ff5b3c --- /dev/null +++ b/README.zh.md @@ -0,0 +1,35 @@ +[English](README.md) + +## 简介 + +liveship 是一个小巧易用的直播录制工具,目前已支持抖音、虎牙、小红书、youtube、tiktok、twitch,未来计划添加更多平台支持。 + +## 工作原理 + +liveship 本质上只是 ffmpeg 套壳,通过模拟请求获取直播流地址,然后使用 ffmpeg 进行录制。因此要求您的电脑上必须安装有 ffmpeg,并在“程序设置”页面指定 ffmpeg 路径。 + +## 技术栈 + +自豪的使用 rust、tauri 和 svelte 5 构建。 + +## 使用方法 + +liveship 是一个基于 tauri 的桌面应用程序,您可以从 [release](https://github.com/jlvihv/liveship/releases/) 页面下载对应平台的二进制文件,然后安装运行。 + +## 常见问题 + +1. mac os 提示“文件已损坏,无法打开”:这是因为 mac os 限制了非 app store 的应用程序,您可以在终端中执行 `sudo xattr -d com.apple.quarantine /Applications/liveship.app` 命令解除限制。 + +## 特别鸣谢 + +直播源解析的代码很大程度上参考了 [DouyinLiveRecorder](https://github.com/ihmily/DouyinLiveRecorder) 项目,在此致以诚挚的感谢。 + +## 特别说明 + +liveship 计划在 1.0 版本之后添加收费功能,作为我独立开发人生道路的探索。但在 1.0 之前,所有功能都是开源免费的,期待您的建议和反馈。 + +## License + +CC BY-NC (Creative Commons Attribution-NonCommercial): + +允许复制、发行、展示和表演作品及其衍生作品,但仅限于非商业用途。 diff --git a/bun.lockb b/bun.lockb index b783c00..54ee432 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index a9cf985..e7f4d4a 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "@iconify-json/icomoon-free": "^1.1.8", "@iconify/tailwind": "^1.1.1", "@sveltejs/adapter-static": "^3.0.2", - "@sveltejs/kit": "^2.5.11", + "@sveltejs/kit": "^2.5.16", "@sveltejs/vite-plugin-svelte": "^3.1.1", "@tauri-apps/cli": "^2.0.0-beta.20", "autoprefixer": "^10.4.19", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 774a35b..045867b 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -17,6 +17,30 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom 0.2.15", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.3" @@ -132,6 +156,19 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "async-compression" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd066d0b4ef8ecb03a55319dc13aa6910616d0f44008a045bb1835af830abff5" +dependencies = [ + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", +] + [[package]] name = "async-executor" version = "1.12.0" @@ -379,6 +416,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] + [[package]] name = "block2" version = "0.5.1" @@ -401,6 +447,144 @@ dependencies = [ "piper", ] +[[package]] +name = "boa_ast" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73498e9b2f0aa7db74977afa4d594657611e90587abf0dd564c0b55b4a130163" +dependencies = [ + "bitflags 2.5.0", + "boa_interner", + "boa_macros", + "indexmap 2.2.6", + "num-bigint", + "rustc-hash", +] + +[[package]] +name = "boa_engine" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16377479d5d6d33896e7acdd1cc698d04a8f72004025bbbddf47558cd29146a6" +dependencies = [ + "bitflags 2.5.0", + "boa_ast", + "boa_gc", + "boa_icu_provider", + "boa_interner", + "boa_macros", + "boa_parser", + "boa_profiler", + "chrono", + "dashmap", + "fast-float", + "icu_normalizer", + "indexmap 2.2.6", + "itertools 0.11.0", + "num-bigint", + "num-integer", + "num-traits", + "num_enum 0.6.1", + "once_cell", + "pollster", + "rand 0.8.5", + "regress", + "rustc-hash", + "ryu-js", + "serde", + "serde_json", + "sptr", + "static_assertions", + "tap", + "thin-vec", + "thiserror", +] + +[[package]] +name = "boa_gc" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c97b44beaef9d4452342d117d94607fdfa8d474280f1ba0fd97853834e3a49b2" +dependencies = [ + "boa_macros", + "boa_profiler", + "thin-vec", +] + +[[package]] +name = "boa_icu_provider" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b30e52e34e451dd0bfc2c654a9a43ed34b0073dbd4ae3394b40313edda8627aa" +dependencies = [ + "icu_collections", + "icu_normalizer", + "icu_properties", + "icu_provider", + "icu_provider_adapters", + "icu_provider_blob", + "once_cell", +] + +[[package]] +name = "boa_interner" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3e5afa991908cfbe79bd3109b824e473a1dc5f74f31fab91bb44c9e245daa77" +dependencies = [ + "boa_gc", + "boa_macros", + "hashbrown 0.14.5", + "indexmap 2.2.6", + "once_cell", + "phf 0.11.2", + "rustc-hash", + "static_assertions", +] + +[[package]] +name = "boa_macros" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "005fa0c5bd20805466dda55eb34cd709bb31a2592bb26927b47714eeed6914d8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "synstructure", +] + +[[package]] +name = "boa_parser" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e09afb035377a9044443b598187a7d34cd13164617182a4d7c348522ee3f052" +dependencies = [ + "bitflags 2.5.0", + "boa_ast", + "boa_icu_provider", + "boa_interner", + "boa_macros", + "boa_profiler", + "fast-float", + "icu_locid", + "icu_properties", + "icu_provider", + "icu_provider_macros", + "num-bigint", + "num-traits", + "once_cell", + "regress", + "rustc-hash", + "tinystr", +] + +[[package]] +name = "boa_profiler" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3190f92dfe48224adc92881c620f08ccf37ff62b91a094bb357fe53bd5e84647" + [[package]] name = "brotli" version = "3.5.0" @@ -528,6 +712,15 @@ dependencies = [ "toml 0.8.2", ] +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + [[package]] name = "cc" version = "1.0.99" @@ -593,6 +786,22 @@ dependencies = [ "windows-targets 0.52.5", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + [[package]] name = "cocoa" version = "0.25.0" @@ -740,6 +949,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "critical-section" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" + [[package]] name = "crossbeam-channel" version = "0.5.13" @@ -807,6 +1022,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "cssparser" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b3df4f93e5fbbe73ec01ec8d3f68bba73107993a5b1e7519273c32db9b0d5be" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa 1.0.11", + "phf 0.11.2", + "smallvec", +] + [[package]] name = "cssparser-macros" version = "0.6.1" @@ -872,7 +1100,7 @@ dependencies = [ "hashbrown 0.14.5", "lock_api", "once_cell", - "parking_lot_core", + "parking_lot_core 0.9.10", ] [[package]] @@ -1052,6 +1280,12 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" +[[package]] +name = "ego-tree" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a68a4904193147e0a8dec3314640e6db742afd5f6e634f428a6af230d9b3591" + [[package]] name = "either" version = "1.12.0" @@ -1078,6 +1312,12 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + [[package]] name = "encoding_rs" version = "0.8.34" @@ -1167,6 +1407,12 @@ dependencies = [ "zune-inflate", ] +[[package]] +name = "fast-float" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95765f67b4b18863968b4a1bd5bb576f732b29a4a28c7cd84c09fa3e2875f33c" + [[package]] name = "fastrand" version = "2.1.0" @@ -1287,6 +1533,21 @@ dependencies = [ "new_debug_unreachable", ] +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.30" @@ -1294,6 +1555,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -1361,6 +1623,7 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ + "futures-channel", "futures-core", "futures-io", "futures-macro", @@ -1503,6 +1766,15 @@ dependencies = [ "version_check", ] +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + [[package]] name = "getrandom" version = "0.1.16" @@ -1521,8 +1793,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -1724,6 +1998,15 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + [[package]] name = "hashbrown" version = "0.14.5" @@ -1916,11 +2199,12 @@ dependencies = [ [[package]] name = "icu_collections" -version = "1.5.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +checksum = "ef8302d8dfd6044d3ddb3f807a5ef3d7bbca9a574959c6d6e4dc39aa7012d0d5" dependencies = [ "displaydoc", + "serde", "yoke", "zerofrom", "zerovec", @@ -1928,48 +2212,29 @@ dependencies = [ [[package]] name = "icu_locid" -version = "1.5.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +checksum = "3003f85dccfc0e238ff567693248c59153a46f4e6125ba4020b973cef4d1d335" dependencies = [ "displaydoc", "litemap", + "serde", "tinystr", "writeable", "zerovec", ] -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - [[package]] name = "icu_normalizer" -version = "1.5.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +checksum = "652869735c9fb9f5a64ba180ee16f2c848390469c116deef517ecc53f4343598" dependencies = [ "displaydoc", "icu_collections", - "icu_normalizer_data", "icu_properties", "icu_provider", + "serde", "smallvec", "utf16_iter", "utf8_iter", @@ -1977,59 +2242,75 @@ dependencies = [ "zerovec", ] -[[package]] -name = "icu_normalizer_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" - [[package]] name = "icu_properties" -version = "1.5.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036" +checksum = "ce0e1aa26851f16c9e04412a5911c86b7f8768dac8f8d4c5f1c568a7e5d7a434" dependencies = [ "displaydoc", "icu_collections", - "icu_locid_transform", - "icu_properties_data", "icu_provider", + "serde", "tinystr", "zerovec", ] -[[package]] -name = "icu_properties_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" - [[package]] name = "icu_provider" -version = "1.5.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +checksum = "8dc312a7b6148f7dfe098047ae2494d12d4034f48ade58d4f353000db376e305" dependencies = [ "displaydoc", "icu_locid", "icu_provider_macros", + "postcard", + "serde", "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", "zerovec", ] +[[package]] +name = "icu_provider_adapters" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ae1e2bd0c41728b77e7c46e9afdec5e2127d1eedacc684724667d50c126bd3" +dependencies = [ + "icu_locid", + "icu_provider", + "serde", + "tinystr", + "yoke", + "zerovec", +] + +[[package]] +name = "icu_provider_blob" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd364c9a01f791a4bc04a74cf2a1d01d9f6926a40fd5ae1c28004e1e70d8338b" +dependencies = [ + "icu_provider", + "postcard", + "serde", + "writeable", + "yoke", + "zerovec", +] + [[package]] name = "icu_provider_macros" -version = "1.5.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +checksum = "dd8b728b9421e93eff1d9f8681101b78fa745e0748c95c655c83f337044a7e10" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 1.0.109", ] [[package]] @@ -2050,14 +2331,12 @@ dependencies = [ [[package]] name = "idna" -version = "1.0.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "icu_normalizer", - "icu_properties", - "smallvec", - "utf8_iter", + "unicode-bidi", + "unicode-normalization", ] [[package]] @@ -2130,6 +2409,16 @@ dependencies = [ "cfb", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "block-padding", + "generic-array", +] + [[package]] name = "instant" version = "0.1.13" @@ -2137,6 +2426,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", ] [[package]] @@ -2175,6 +2467,15 @@ dependencies = [ "once_cell", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.12.1" @@ -2293,11 +2594,11 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f29e4755b7b995046f510a7520c42b2fed58b77bd94d5a87a8eb43d2fd126da8" dependencies = [ - "cssparser", + "cssparser 0.27.2", "html5ever", "indexmap 1.9.3", "matches", - "selectors", + "selectors 0.22.0", ] [[package]] @@ -2403,7 +2704,7 @@ checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" [[package]] name = "liveship" -version = "0.1.17" +version = "0.1.18" dependencies = [ "anyhow", "async-trait", @@ -2415,6 +2716,7 @@ dependencies = [ "once_cell", "redb", "reqwest", + "rusty_ytdl", "serde", "serde_json", "showfile", @@ -2468,6 +2770,16 @@ dependencies = [ "imgref", ] +[[package]] +name = "m3u8-rs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f03cd3335fb5f2447755d45cda9c70f76013626a9db44374973791b0926a86c3" +dependencies = [ + "chrono", + "nom", +] + [[package]] name = "mac" version = "0.1.1" @@ -2624,7 +2936,7 @@ dependencies = [ "bitflags 1.3.2", "jni-sys", "ndk-sys", - "num_enum", + "num_enum 0.5.11", "raw-window-handle 0.5.2", "thiserror", ] @@ -2715,6 +3027,7 @@ checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" dependencies = [ "num-integer", "num-traits", + "serde", ] [[package]] @@ -2779,7 +3092,16 @@ version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" dependencies = [ - "num_enum_derive", + "num_enum_derive 0.5.11", +] + +[[package]] +name = "num_enum" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" +dependencies = [ + "num_enum_derive 0.6.1", ] [[package]] @@ -2794,6 +3116,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "num_enum_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "objc" version = "0.2.7" @@ -2947,6 +3281,10 @@ name = "once_cell" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +dependencies = [ + "critical-section", + "portable-atomic", +] [[package]] name = "open" @@ -3066,6 +3404,17 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + [[package]] name = "parking_lot" version = "0.12.3" @@ -3073,7 +3422,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", - "parking_lot_core", + "parking_lot_core 0.9.10", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall 0.2.16", + "smallvec", + "winapi", ] [[package]] @@ -3084,7 +3447,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.2", "smallvec", "windows-targets 0.52.5", ] @@ -3332,6 +3695,29 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "pollster" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" + +[[package]] +name = "portable-atomic" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" + +[[package]] +name = "postcard" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" +dependencies = [ + "cobs", + "embedded-io", + "serde", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -3572,7 +3958,7 @@ dependencies = [ "built", "cfg-if", "interpolate_name", - "itertools", + "itertools 0.12.1", "libc", "libfuzzer-sys", "log", @@ -3649,6 +4035,15 @@ dependencies = [ "libc", ] +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_syscall" version = "0.5.2" @@ -3713,12 +4108,23 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +[[package]] +name = "regress" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82a9ecfa0cb04d0b04dddb99b8ccf4f66bc8dfd23df694b398570bd8ae3a50fb" +dependencies = [ + "hashbrown 0.13.2", + "memchr", +] + [[package]] name = "reqwest" version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" dependencies = [ + "async-compression", "base64 0.22.1", "bytes", "cookie", @@ -3764,6 +4170,54 @@ dependencies = [ "winreg", ] +[[package]] +name = "reqwest-middleware" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a45d100244a467870f6cb763c4484d010a6bed6bd610b3676e3825d93fb4cfbd" +dependencies = [ + "anyhow", + "async-trait", + "http", + "reqwest", + "serde", + "thiserror", + "tower-service", +] + +[[package]] +name = "reqwest-retry" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40f342894422862af74c50e1e9601cf0931accc9c6981e5eb413c46603b616b5" +dependencies = [ + "anyhow", + "async-trait", + "chrono", + "futures", + "getrandom 0.2.15", + "http", + "hyper", + "parking_lot 0.11.2", + "reqwest", + "reqwest-middleware", + "retry-policies", + "tokio", + "tracing", + "wasm-timer", +] + +[[package]] +name = "retry-policies" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "493b4243e32d6eedd29f9a398896e35c6943a123b55eec97dcaee98310d25810" +dependencies = [ + "anyhow", + "chrono", + "rand 0.8.5", +] + [[package]] name = "rfd" version = "0.14.1" @@ -3840,6 +4294,12 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc_version" version = "0.4.0" @@ -3909,12 +4369,50 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +[[package]] +name = "rusty_ytdl" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad6999f80c14e0325c3e19178ecfe70cc3834e96fbea8f4581fd356ab7752c62" +dependencies = [ + "aes", + "async-trait", + "boa_engine", + "bytes", + "cbc", + "derivative", + "derive_more", + "hex", + "m3u8-rs", + "mime", + "once_cell", + "rand 0.8.5", + "regex", + "reqwest", + "reqwest-middleware", + "reqwest-retry", + "scraper", + "serde", + "serde_json", + "serde_qs", + "thiserror", + "tokio", + "url", + "urlencoding", +] + [[package]] name = "ryu" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "ryu-js" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6518fc26bced4d53678a22d6e423e9d8716377def84545fe328236e3af070e7f" + [[package]] name = "same-file" version = "1.0.6" @@ -3971,6 +4469,22 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scraper" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b80b33679ff7a0ea53d37f3b39de77ea0c75b12c5805ac43ec0c33b3051af1b" +dependencies = [ + "ahash", + "cssparser 0.31.2", + "ego-tree", + "getopts", + "html5ever", + "once_cell", + "selectors 0.25.0", + "tendril", +] + [[package]] name = "security-framework" version = "2.11.0" @@ -4001,7 +4515,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" dependencies = [ "bitflags 1.3.2", - "cssparser", + "cssparser 0.27.2", "derive_more", "fxhash", "log", @@ -4009,11 +4523,30 @@ dependencies = [ "phf 0.8.0", "phf_codegen 0.8.0", "precomputed-hash", - "servo_arc", + "servo_arc 0.1.1", "smallvec", "thin-slice", ] +[[package]] +name = "selectors" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06" +dependencies = [ + "bitflags 2.5.0", + "cssparser 0.31.2", + "derive_more", + "fxhash", + "log", + "new_debug_unreachable", + "phf 0.10.1", + "phf_codegen 0.10.0", + "precomputed-hash", + "servo_arc 0.3.0", + "smallvec", +] + [[package]] name = "semver" version = "1.0.23" @@ -4065,6 +4598,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_qs" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd34f36fe4c5ba9654417139a9b3a20d2e1de6012ee678ad14d240c22c78d8d6" +dependencies = [ + "percent-encoding", + "serde", + "thiserror", +] + [[package]] name = "serde_repr" version = "0.1.19" @@ -4159,6 +4703,15 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "servo_arc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d036d71a959e00c77a63538b90a6c2390969f9772b096ea837205c6bd0491a44" +dependencies = [ + "stable_deref_trait", +] + [[package]] name = "sha1" version = "0.10.6" @@ -4284,7 +4837,7 @@ dependencies = [ "objc2-foundation", "objc2-quartz-core", "raw-window-handle 0.6.2", - "redox_syscall", + "redox_syscall 0.5.2", "wasm-bindgen", "wayland-sys", "web-sys", @@ -4326,6 +4879,12 @@ dependencies = [ "lock_api", ] +[[package]] +name = "sptr" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a" + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -4355,7 +4914,7 @@ checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" dependencies = [ "new_debug_unreachable", "once_cell", - "parking_lot", + "parking_lot 0.12.3", "phf_shared 0.10.0", "precomputed-hash", "serde", @@ -4518,7 +5077,7 @@ dependencies = [ "ndk-sys", "objc", "once_cell", - "parking_lot", + "parking_lot 0.12.3", "raw-window-handle 0.6.2", "scopeguard", "tao-macros", @@ -4541,6 +5100,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "target-lexicon" version = "0.12.14" @@ -4886,6 +5451,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" +[[package]] +name = "thin-vec" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a38c90d48152c236a3ab59271da4f4ae63d678c5d7ad6b7714d7cb9760be5e4b" + [[package]] name = "thiserror" version = "1.0.61" @@ -4960,11 +5531,12 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.6" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +checksum = "8faa444297615a4e020acb64146b0603c9c395c03a97c17fd9028816d3b4d63e" dependencies = [ "displaydoc", + "serde", "zerovec", ] @@ -5305,6 +5877,12 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +[[package]] +name = "unicode-width" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" + [[package]] name = "untrusted" version = "0.9.0" @@ -5313,12 +5891,12 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", - "idna 1.0.0", + "idna 0.5.0", "percent-encoding", "serde", ] @@ -5534,6 +6112,21 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasm-timer" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" +dependencies = [ + "futures", + "js-sys", + "parking_lot 0.11.2", + "pin-utils", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "wayland-sys" version = "0.31.2" @@ -6226,6 +6819,26 @@ dependencies = [ "zvariant", ] +[[package]] +name = "zerocopy" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "zerofrom" version = "0.1.4" @@ -6255,10 +6868,11 @@ checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" [[package]] name = "zerovec" -version = "0.10.2" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c" +checksum = "591691014119b87047ead4dcf3e6adfbf73cb7c38ab6980d4f18a32138f35d46" dependencies = [ + "serde", "yoke", "zerofrom", "zerovec-derive", @@ -6266,9 +6880,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.2" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" +checksum = "7a4a1638a1934450809c2266a70362bfc96cd90550c073f5b8a55014d1010157" dependencies = [ "proc-macro2", "quote", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 03dd6d4..06b423a 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "liveship" -version = "0.1.17" -description = "liveship 是一个直播录制工具,目前已支持抖音、虎牙、小红书、tiktok、twitch" +version = "0.1.18" +description = "liveship 是一个直播录制工具,目前已支持抖音、虎牙、小红书、youtube、tiktok、twitch" authors = ["jlvihv"] email = "imvihv@gmail.com" edition = "2021" @@ -36,6 +36,7 @@ tokio = { version = "1.38", features = ["rt-multi-thread", "macros"] } showfile = "0.1" ffmpeg-sidecar = "1.1" image = "0.25" +rusty_ytdl = "0.7" [profile.release] strip = true diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 24034fd..9f641a4 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -56,6 +56,7 @@ pub fn run() { manager::request_api::request, manager::request_api::try_request_get_status, manager::request_api::request_post, + manager::my_utils::get_youtube_info, ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/src-tauri/src/manager.rs b/src-tauri/src/manager.rs index b687b6f..f030411 100644 --- a/src-tauri/src/manager.rs +++ b/src-tauri/src/manager.rs @@ -482,3 +482,19 @@ pub mod request_api { Ok(resp) } } + +pub mod my_utils { + use rusty_ytdl::{Video, VideoInfo}; + + use super::*; + + #[tauri::command] + pub async fn get_youtube_info(url: String) -> Result { + let video = Video::new(&url).map_err(|e| format!("Could not get video info: {}", e))?; + let video_info = video + .get_info() + .await + .map_err(|e| format!("Could not get video info: {}", e))?; + Ok(video_info) + } +} diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 2de11b1..9e027f5 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,6 +1,6 @@ { "productName": "liveship", - "version": "0.1.17", + "version": "0.1.18", "identifier": "app.happyship.liveship", "build": { "beforeDevCommand": "bun run dev", diff --git a/src/lib/i18n/cn.json b/src/lib/i18n/cn.json index 2745ef6..b336386 100644 --- a/src/lib/i18n/cn.json +++ b/src/lib/i18n/cn.json @@ -118,7 +118,7 @@ "hd_30": "高清30帧", "sd1": "标清", "sd": "标清", - "sd2": "标清", + "sd2": "标清 2", "ld": "流畅", "ld1": "流畅", "ld2": "流畅", @@ -136,5 +136,6 @@ "uhd_60": "超高清60帧", "recentSearch": "最近查询", "tryThese": "不知道如何开始?试试这些", - "gotoRecordHistory": "去录制历史中查看" + "gotoRecordHistory": "去录制历史中查看", + "parseError": "解析直播流地址错误,请刷新试试" } diff --git a/src/lib/i18n/en.json b/src/lib/i18n/en.json index ac4a733..7dee79a 100644 --- a/src/lib/i18n/en.json +++ b/src/lib/i18n/en.json @@ -110,7 +110,6 @@ "origin": "Original", "source": "Original", "full_hd1": "Full HD", - "FULL_HD1": "Full HD", "hd1": "HD", "uhd": "Ultra HD", "hd": "HD", @@ -121,7 +120,6 @@ "sd": "SD", "sd1": "SD", "sd2": "SD", - "SD2": "SD", "ld": "Smooth", "ld1": "Smooth", "ld2": "Smooth", @@ -139,5 +137,6 @@ "uhd_60": "Ultra HD 60fps", "recentSearch": "Recent search", "tryThese": "Don't know how to start? Try these", - "gotoRecordHistory": "Go to record history to view" + "gotoRecordHistory": "Go to record history to view", + "parseError": "Failed to parse live stream address, please refresh and try again" } diff --git a/src/lib/platform/douyin.ts b/src/lib/platform/douyin.ts index 456b55a..b76a285 100644 --- a/src/lib/platform/douyin.ts +++ b/src/lib/platform/douyin.ts @@ -21,6 +21,7 @@ export async function getLiveInfoForDouyin(url: string): Promise { headers: getHeaders() }); let html = await resp.text(); + console.log('douyin html', html); // 解析 html,填充 LiveInfo parseHtmlAndFillLiveInfo(html, info); } catch (e) { diff --git a/src/lib/platform/youtube.ts b/src/lib/platform/youtube.ts index c929828..1bc9de5 100644 --- a/src/lib/platform/youtube.ts +++ b/src/lib/platform/youtube.ts @@ -1,7 +1,5 @@ -import { LiveStatus, PlatformKind, StreamingProtocol, type LiveInfo, type Stream } from '@/model'; +import { LiveStatus, PlatformKind, StreamingProtocol, type LiveInfo } from '@/model'; import { invoke } from '@tauri-apps/api/core'; -import { JSONPath } from 'jsonpath-plus'; -import { fetch } from '@tauri-apps/plugin-http'; export async function getLiveInfoForYoutube(url: string): Promise { let info: LiveInfo = { @@ -16,155 +14,25 @@ export async function getLiveInfoForYoutube(url: string): Promise { status: LiveStatus.NotLive }; try { - let videoId = url.split('v=')[1]; - console.log('youtube video id', videoId); - let resp = await fetch(url, { - method: 'GET', - headers: { - 'User-Agent': - 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' - } - }); - let html = await resp.text(); - console.log('youtube html', html); - - // _re_ytInitialPlayerResponse = re.compile(r"""var\s+ytInitialPlayerResponse\s*=\s*({.*?});\s*var\s+\w+\s*=""", re.DOTALL) - let data = html.match(/var\s+ytInitialPlayerResponse\s*=\s*({.*?});\s*var\s+\w+\s*=/); - console.log('youtube data', data); - if (!data || data.length < 2) { - return info; - } - const initialPlayerResponse = JSON.parse(data[1]); - const streamingData = initialPlayerResponse.streamingData; - console.log('youtube streaming data', streamingData); - if (!streamingData) { - return info; - } - info.status = LiveStatus.Live; - info.streams.push({ - url: streamingData.hlsManifestUrl, - protocol: StreamingProtocol.Hls, - resolution: 'default' - }); - // 遍历 streamingData.adaptiveFormats,全都放入 info.streams - for (let format of streamingData.adaptiveFormats) { - console.log('youtube format', format.signatureCipher); + let youtubeInfo: any = await invoke('get_youtube_info', { url }); + console.log('youtube info', youtubeInfo); + info.status = youtubeInfo.videoDetails.isLiveContent ? LiveStatus.Live : LiveStatus.NotLive; + info.viewerCount = youtubeInfo.videoDetails.viewCount; + info.title = youtubeInfo.videoDetails.title; + info.anchorName = youtubeInfo.videoDetails.author.name; + info.anchorAvatar = youtubeInfo.videoDetails.author.thumbnails[0].url; + info.roomCover = youtubeInfo.videoDetails.thumbnails[0].url || ''; + for (let format of youtubeInfo.formats) { info.streams.push({ - url: format.signatureCipher.split('url=')[1], - protocol: StreamingProtocol.Hls, - resolution: format.quality + url: format.url, + protocol: format.isHLS ? StreamingProtocol.Hls : StreamingProtocol.Flv, + resolution: format.qualityLabel }); } - - // const embedUrl = `https://www.youtube.com/embed/${videoId}`; - // let resp = await invoke('request', { url: embedUrl, headers: {} }); - // console.log('embed', resp); - - // let channelIdArray = (resp as string).match(/\\"channelId\\":\\"(.{24})\\"/); - // let channelId = channelIdArray ? channelIdArray[1] : ''; - - // const apiUrl = - // 'https://www.youtube.com/youtubei/v1/browse?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8'; - // let response = await invoke('request_post', { - // url: apiUrl, - // headers: {}, - // body: { - // context: { - // client: { - // hl: 'zh-CN', - // clientName: 'MWEB', - // clientVersion: '2.20230101.00.00', - // timeZone: 'Asia/Shanghai' - // } - // }, - // browseId: channelId, - // params: 'EgdzdHJlYW1z8gYECgJ6AA%3D%3D' - // } - // }); - // // match $..videoWithContextRenderer - // console.log('youtube api response', response); - // let apiJson = JSON.parse(response as string); - // console.log('youtube api response', apiJson); - // let videoWithContextRederer = JSONPath({ path: '$..videoWithContextRenderer', json: apiJson }); - // console.log('videoWithContextRederer', videoWithContextRederer); - // // 遍历 videoWithContextRederer,找到直播视频 - // for (let video of videoWithContextRederer) { - // } - - // let channelUrl = `https://www.youtube.com/channel/${channelId}/videos`; - // console.log('channel url', channelUrl); - // let channelResp = await invoke('request', { url: channelUrl, headers: {} }); - // console.log('channel', channelResp); - // // r'"gridVideoRenderer"((.(?!"gridVideoRenderer"))(?!"style":"UPCOMING"))+"label":"(LIVE|LIVE NOW|PREMIERING NOW)"([\s\S](?!"style":"UPCOMING"))+?("gridVideoRenderer"|)', - // let liveVideoArray = (channelResp as string).match( - // /r'"gridVideoRenderer"((.(?!"gridVideoRenderer"))(?!"style":"UPCOMING"))+"label":"(LIVE|LIVE NOW|PREMIERING NOW)"([\s\S](?!"style":"UPCOMING"))+?("gridVideoRenderer"|<\/script>)/ - // ); - // console.log('liveVideoArray', liveVideoArray); - // let liveVideo = liveVideoArray ? liveVideoArray[1] : ''; } catch (e) { - console.error('get live info for tiktok failed: ', e); + console.error('get live info for youtube failed: ', e); // 抛出一个错误 throw e; } return info; } - -// 解析 html,填充 LiveInfo -function parseHtmlAndFillLiveInfo(html: string, info: LiveInfo) { - // match {#snippet icon(platformKind:string)} -
- {platformKind} -
+ {platformKind} {/snippet} @@ -329,12 +319,11 @@
{#if liveInfo?.status === LiveStatus.Live} -

+

{@render icon(liveInfo?.platformKind)} - {liveInfo?.title} - {#if recordStatus === RecordingStatus.Recording} - {$t('recording')} - {/if} +

+ {liveInfo?.title} +

{:else if liveInfo?.status === LiveStatus.NotLive}
@@ -386,6 +375,9 @@ {liveInfo.anchorName}

{$t('living')}

+ {#if recordStatus === RecordingStatus.Recording} + {$t('recording')} + {/if}

{liveInfo.viewerCount ? liveInfo.viewerCount + $t('watching') : ''}

@@ -401,7 +393,7 @@ > {#each liveInfo.streams as item} {item.protocol + ' ' + $t(item.resolution.toLowerCase())} {/each} @@ -490,60 +482,58 @@ {/if}
{:else} -
-
- {#if queryHistory.length <= 5} -

{$t('tryThese')}

-
- {#each tryLinks as link} -
- -
- {/each} -
- {:else} -

{$t('recentSearch')}

- {#each queryHistory as history} +
+ {#if queryHistory.length <= 5} +

{$t('tryThese')}

+
+ {#each tryLinks as link}
-
{/each} - {/if} -
+
+ {:else} +

{$t('recentSearch')}

+ {#each queryHistory as history} +
+ + +
+ {/each} + {/if}
{/if}
diff --git a/static/bilibili.ico b/static/bilibili.ico new file mode 100644 index 0000000..628ecb4 Binary files /dev/null and b/static/bilibili.ico differ diff --git a/static/douyin.ico b/static/douyin.ico new file mode 100644 index 0000000..637ab31 Binary files /dev/null and b/static/douyin.ico differ diff --git a/static/douyu.ico b/static/douyu.ico new file mode 100644 index 0000000..b49c072 Binary files /dev/null and b/static/douyu.ico differ diff --git a/static/huya.ico b/static/huya.ico new file mode 100644 index 0000000..e5c13f0 Binary files /dev/null and b/static/huya.ico differ diff --git a/static/kuaishou.ico b/static/kuaishou.ico new file mode 100644 index 0000000..ba7dac3 Binary files /dev/null and b/static/kuaishou.ico differ diff --git a/static/tiktok.ico b/static/tiktok.ico new file mode 100644 index 0000000..ddcb963 Binary files /dev/null and b/static/tiktok.ico differ diff --git a/static/twitch.ico b/static/twitch.ico new file mode 100644 index 0000000..bdbac49 Binary files /dev/null and b/static/twitch.ico differ diff --git a/static/xiaohongshu.ico b/static/xiaohongshu.ico new file mode 100644 index 0000000..8b48924 Binary files /dev/null and b/static/xiaohongshu.ico differ diff --git a/static/youtube.ico b/static/youtube.ico new file mode 100644 index 0000000..f4d9664 Binary files /dev/null and b/static/youtube.ico differ diff --git a/static/youtube.png b/static/youtube.png new file mode 100644 index 0000000..e143c55 Binary files /dev/null and b/static/youtube.png differ