Borber / seam

获取多直播平台的直播源
https://t.me/seam_rust
MIT License
870 stars 108 forks source link

Node结构体是否可以增强一下,以及是否可以使用trait bound约束接口 #22

Open eweca-d opened 1 year ago

eweca-d commented 1 year ago

Node结构体是否可以增强一下,现在的标准Node结构体是:

#[derive(Serialize, Debug)]
pub struct Node {
    /// 清晰度
    pub rate: String,
    /// 直播源地址 后续考虑使用数组来安装
    pub url: String,
}

这个结构体太过简略了,大部分情况下,我们至少还希望获取直播流的格式,比如BILIBILI经常能获取的可选直播流格式为“TS/FLV...”,在之前的pr中我强行将rate格式为"[格式]-[清晰度][线路编号]”,这或许不是一个较好的选择。一个我建议的构建思路如下:

#[derive(Debug)]
pub enum ShowType {
    /// 返回直播源地址
    On(NodeList),
    Off,
    Error(String),
}

#[derive(Serialize, Debug)]
pub struct NodeList {
    pub nodes: Vec<Node>,
}

#[derive(Serialize, Debug)]
pub struct Node {
    /// 格式
    pub format: Format,
    /// 清晰度
    pub rate: Rate,
    /// 线路(虚拟)
    pub channel: usize,
    /// 直播源地址 后续考虑使用数组来安装
    pub url: String,
}

#[derive(Serialize, Debug)]
pub struct Rate{
    pub rate: usize,
    pub label: String,
}

#[derive(Serialize, Debug)]
pub enum Format {
    FLV,
    TS,
    Other(String),
}

同上,此时我们有了详细的Rate信息(以usize计),意味着我们可以使用std::cmp::PartialOrd这一类的标注库trait进行Node的排序,从而完成路线中“根据画质排序”的承诺。另外label用来标记“原画/高清”之类的tag,由于每个平台可能使用的tag不同,这个需要由各个直播模块自行指定。

Format格式进行type化则是有利于以后假如引入下载功能后的程序编写。

以上各struct可以使用的new,push之类的impl以便各直播子模块使用。


另一个提案是有关于接口规范化的。目前的程序其实内含一个强制性约定的get函数,所以要不要尝试下比如trait bound一类的东西,比如引入:

use async_trait::async_trait;

#[async_trait]
pub trait URL {
    async fn get_url(&self) -> Result<ShowType>;
}

#[async_trait]
pub trait Download {
    async fn download(&self) -> Result<()>;
}

然后对于每个直播模块,可以有:

use async_trait::async_trait;

pub struct Bilibili(String);

impl From<String> for Bilibili {
    fn from(rid: String) -> Self {
        Self(rid)
    }
}

#[async_trait]
impl URL for Bilibili {
    async fn get_url(&self) -> Result<ShowType> {
        get(self.0.as_str()).await
    }
}

这个其实意义不大,我就是觉得蛮有意思的,而且更rustacean。

同样有个蛮有意思的就是使用宏来match arg.command。match的command太多略丑陋,写个宏应该能实现类似match_command!(Bili, Douyu, Huya)这种格式,这个也是纯娱乐,实际对于程序的性能没啥提高。

最后,modle.rs是不是应该是model.rs,貌似单词拼错啦?

Borber commented 1 year ago

嗯嗯,

  1. Node的字段确实有点太模糊了, 其实在现在的使用中 也是很粗糙的吧 格式放到了rate中,这块肯定是会改造的, 你的想法和我不谋而合。
  2. 清晰度这个我还在考虑, 因为大家对于低画质的需求可能不是很大, 甚至有一些需求就是在不登陆的情况下看最高请的视频, 我们可以讨论一下是否默认只提供不同cdn线路的最高清的链接, 同时提供所有清晰度的cdn链接好像会让数量多很多,且用的人少
  3. 接口规范化这个是绝好的建议,但我对这块其实不太熟悉 (汗(lll¬ω¬)) 还需要去学习一下,(大佬好强) 但看起来也很可行,规范而优雅的代码不仅自己写起来舒服, 后面参与的人也能更快的融入, 所以意义不小,既然知道了这块肯定是会加入进来。 rustacean!
  4. 宏实现子命令匹配这个也很棒, 我们写代码快乐最重要, 性能只要不降低能更好看更优雅就是很大的提升了。
  5. model 确实写错了, 🤣

感谢大佬的建议, 也期待之后的pr . 在此也向大佬报告一下后续的计划,

项目前期主要适配大量平台的工作进展比较顺利, 随后是优化代码, 调整结构, 提取到core中共用代码, 但后期会在单纯单个房间获取上转变为订阅主播, 做到一个软件订阅全平台主播, 一键获取所有开播主播的直播源 .

随后在订阅主播的功能开发完毕后将开始区分cliserver, cli 主打便捷性, 订阅的主播开播时自动通知用户, 以及自动录制功能, server端将使用deno为js运行环境, 并提供api, 为GUI准备,

我不打算将处理逻辑直接放入GUI中, 而是将server作为后端, GUI与之交互, 也为之后的网络部署服务端, 本地客户端做准备.

以上是目前的不成熟的想法 还请大佬指摘

eweca-d commented 1 year ago

大佬不敢当,哈哈,我也是在rust新手,如果后续有一些PR有一些不工程化/不优雅/逻辑不对的地方,请一定指出让我返修!

订阅主播和自动录制是个绝妙的主意,相同的逻辑我在B站录播姬上有看到过。录播姬的架构真的让我学习到了不少,如果你之前没看过这个项目,我会强烈推荐你去看看它。我觉得GUI只单纯作为展示层是个好主意,我脑补这个逻辑与我之前写个人网站一样,GUI类似于前端展示哈哈。非常解耦也非常容易让参与者理解结构。

  1. 关于node的提议我非常认同,在有高画质的情况下主动选择低画质的需求不是很强烈,但我觉得或许提示下目前源的“最高清晰度“或许有其价值。(B站不用,因为通常都有原画,但是我不太了解其他直播平台是否大部分情况下能获取类似原画的画质)。所以个人观点是,可以只提供最高画质的源(包含不同格式的),但是可以标注下最高画质具体是原画还是蓝光还是高清之类的。

  2. 接口规范化部分rust基本都是基于trait的,清晰的trait等同于约定,确实能对多人开发和实现多态有帮助的哈哈。期待更新!

  3. 既然你觉得宏命令是个好主意,这个也是改动整体结构最少的PR,我准备试试能不能PR一个初稿。

最后感谢你认真的review和reply!

Borber commented 1 year ago

大佬不敢当,哈哈,我也是在rust新手,如果后续有一些PR有一些不工程化/不优雅/逻辑不对的地方,请一定指出让我返修!

订阅主播和自动录制是个绝妙的主意,相同的逻辑我在B站录播姬上有看到过。录播姬的架构真的让我学习到了不少,如果你之前没看过这个项目,我会强烈推荐你去看看它。我觉得GUI只单纯作为展示层是个好主意,我脑补这个逻辑与我之前写个人网站一样,GUI类似于前端展示哈哈。非常解耦也非常容易让参与者理解结构。

  1. 关于node的提议我非常认同,在有高画质的情况下主动选择低画质的需求不是很强烈,但我觉得或许提示下目前源的“最高清晰度“或许有其价值。(B站不用,因为通常都有原画,但是我不太了解其他直播平台是否大部分情况下能获取类似原画的画质)。所以个人观点是,可以只提供最高画质的源(包含不同格式的),但是可以标注下最高画质具体是原画还是蓝光还是高清之类的。
  2. 接口规范化部分rust基本都是基于trait的,清晰的trait等同于约定,确实能对多人开发和实现多态有帮助的哈哈。期待更新!
  3. 既然你觉得宏命令是个好主意,这个也是改动整体结构最少的PR,我准备试试能不能PR一个初稿。

最后感谢你认真的review和reply!

  1. B站录播姬我之前并没有听说过, 下周一我去学习一下他的架构,
  2. 是的, 最高清晰度的解析每个平台都需要单独适配,但我们可以自己设置更大范围的枚举,例如 原画,蓝光, 超清, 高清,标准, 然后将各平台的清晰度进行大致对应即可。 也方便进行直接匹配转换, 现在的直接字符串拼接确实不太优雅
  3. GUI进行展示但有些本地功能可能还是需要集成, 这块 tauri 的开发经历我有几个但是受限于我的前端水平, GUI开始开发之前讨论一下前端的技术栈吧, 以及 tauri本体的话, 有加 lencx 的群, 到时候可以向他学习,
  4. 接口化规范这块我会快速学习赶上来的
  5. 宏的话还辛苦大佬了,

认真的review是每个程序员的应有的美德, 再次感谢大佬的pr和建议, 大佬不要有压力哦, 以及祝我们新的一年都能快乐编码, 理想开源 ╰(°▽°)╯

eweca-d commented 1 year ago

是的, 最高清晰度的解析每个平台都需要单独适配,但我们可以自己设置更大范围的枚举,例如 原画,蓝光, 超清, 高清,标准, 然后将各平台的清晰度进行大致对应即可。 也方便进行直接匹配转换, 现在的直接字符串拼接确实不太优雅。

我是觉得这些只是tag,单纯用来显示而不用不同的处理方式,其实不太需要用enum来匹配而是让各直播模块自行返回tag是不是会更好一点。而flv和ts之类的属于如果要下载可能需要不同的处理方式的分类,这个用enum可能会好些。

GUI进行展示但有些本地功能可能还是需要集成, 这块 tauri 的开发经历我有几个但是受限于我的前端水平, GUI开始开发之前讨论一下前端的技术栈吧, 以及 tauri本体的话, 有加 lencx 的群, 到时候可以向他学习,

我也写过几个tauri,用的svelte + bulma,也是受限于我稀碎的css和html水平,界面的美观度都挺拉跨的哈哈。这方面我可能很难帮上忙了。

一起探讨,互相学习,快乐编码, 理想开源 ╰(°▽°)╯。

Borber commented 1 year ago

@eweca-d 大佬, 你帮忙看看这样调整结构合理吗 https://github.com/Borber/seam/tree/separate_acquisition_status

eweca-d commented 1 year ago

@Borber 粗略的扫了一眼。我觉得挺好的,就是在想danmu其实还是应该整合进core里去的吧,这样子可以把core做成一个功能完备的库。core可以让cli调用;gui的话可以在core上再搭一层管理层,往上再搭一层显示层这样子。

Borber commented 1 year ago

@Borber 粗略的扫了一眼。我觉得挺好的,就是在想danmu其实还是应该整合进core里去的吧,这样子可以把core做成一个功能完备的库。core可以让cli调用;gui的话可以在core上再搭一层管理层,往上再搭一层显示层这样子。

因为在考虑 server端 好像对danmu这块不好处理

eweca-d commented 1 year ago

也不难处理吧,开三个线程,一个下载danmu,一个下载视频,一个检测直播间状态或者接收停止信号,这样可以么。

Borber commented 1 year ago

也不难处理吧,开三个线程,一个下载danmu,一个下载视频,一个检测直播间状态或者接收停止信号,这样可以么。

不是, 是server 好像不会做弹幕这块的功能

eweca-d commented 1 year ago

@Borber 额,没跟上思路,我尝试捋一捋。意思是最后会出CLI/GUI/SERVER三种端口。然后你想的是server端可以直接播放,但是不做弹幕功能,因为播放器嵌入弹幕这个难度太高,是这个样子么?

Borber commented 1 year ago

@Borber 额,没跟上思路,我尝试捋一捋。意思是最后会出CLI/GUI/SERVER三种端口。然后你想的是server端可以直接播放,但是不做弹幕功能,因为播放器嵌入弹幕这个难度太高,是这个样子么?

嗯嗯,server 用来提供网络解析的接口, 但应该不太方便提供弹幕的接口 GUI就是方便用户直接使用的版本了, 解析和弹幕功能都有,然后加上订阅和通知功能, cli 之后就设计成 方便命令行调用的, 或者挂到服务器上做自动脚本这种