feat: 后端支持获取视频的画质和音质

This commit is contained in:
lanyeeee
2026-02-01 08:45:46 +08:00
parent b4851e4143
commit bfba2a1ab5
10 changed files with 244 additions and 0 deletions
+39
View File
@@ -9,11 +9,13 @@ use crate::{
extensions::AppHandleExt,
logger,
types::{
available_media_formats::AvailableMediaFormats,
bangumi_follow_info::BangumiFollowInfo,
bangumi_info::{BangumiInfo, EpInBangumi},
create_download_task_params::CreateDownloadTaskParams,
fav_folders::FavFolders,
fav_info::FavInfo,
get_available_media_formats_params::GetAvailableMediaFormatsParams,
get_bangumi_follow_info_params::GetBangumiFollowInfoParams,
get_bangumi_info_params::GetBangumiInfoParams,
get_cheese_info_params::GetCheeseInfoParams,
@@ -402,3 +404,40 @@ pub async fn get_skip_segments(
.map_err(|err| CommandError::from("获取跳过片段失败", err))?;
Ok(skip_segments)
}
#[tauri::command(async)]
#[specta::specta]
pub async fn get_available_media_formats(
app: AppHandle,
params: GetAvailableMediaFormatsParams,
) -> CommandResult<AvailableMediaFormats> {
let bili_client = app.get_bili_client();
let result = match params {
GetAvailableMediaFormatsParams::Normal(params) => {
let media_url = bili_client
.get_normal_url(&params.bvid, params.cid)
.await
.map_err(|err| CommandError::from("获取普通视频可用格式失败", err))?;
media_url.to_get_available_media_formats_result()
}
GetAvailableMediaFormatsParams::Bangumi(params) => {
let media_url = bili_client
.get_bangumi_url(params.cid)
.await
.map_err(|err| CommandError::from("获取番剧视频可用格式失败", err))?;
media_url.to_get_available_media_formats_result()
}
GetAvailableMediaFormatsParams::Cheese(params) => {
let media_url = bili_client
.get_cheese_url(params.ep_id)
.await
.map_err(|err| CommandError::from("获取课程视频可用格式失败", err))?;
media_url.to_get_available_media_formats_result()
}
};
Ok(result)
}
+1
View File
@@ -59,6 +59,7 @@ pub fn run() {
get_logs_dir_size,
show_path_in_file_manager,
get_skip_segments,
get_available_media_formats,
])
.events(tauri_specta::collect_events![LogEvent, DownloadEvent]);
+3
View File
@@ -22,10 +22,13 @@ pub enum AudioQuality {
Unknown = -1,
#[serde(rename = "64K")]
#[num_enum(alternatives = [100008])]
Audio64K = 30216,
#[serde(rename = "132K")]
#[num_enum(alternatives = [100009])]
Audio132K = 30232,
#[serde(rename = "192K")]
#[num_enum(alternatives = [100010])]
Audio192K = 30280,
#[serde(rename = "Dolby")]
AudioDolby = 30250,
@@ -0,0 +1,18 @@
use serde::{Deserialize, Serialize};
use specta::Type;
use crate::types::{
audio_quality::AudioQuality, codec_type::CodecType, video_quality::VideoQuality,
};
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
pub struct AvailableMediaFormats {
pub video_qualities_and_codec_types: Vec<VideoQualityAndCodecType>,
pub audio_qualities: Vec<AudioQuality>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
pub struct VideoQualityAndCodecType {
pub video_quality: VideoQuality,
pub codec_type: CodecType,
}
+45
View File
@@ -1,6 +1,11 @@
use serde::{Deserialize, Serialize};
use specta::Type;
use crate::types::{
audio_quality::AudioQuality,
available_media_formats::{AvailableMediaFormats, VideoQualityAndCodecType},
};
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
#[serde(default)]
pub struct BangumiMediaUrl {
@@ -130,3 +135,43 @@ pub struct DurlDetailInBangumi {
pub order: i64,
pub md5: String,
}
impl BangumiMediaUrl {
pub fn to_get_available_media_formats_result(&self) -> AvailableMediaFormats {
let mut video_qualities_and_codec_types: Vec<VideoQualityAndCodecType> = Vec::new();
let mut audio_qualities: Vec<AudioQuality> = Vec::new();
if let Some(dash) = &self.dash {
for media in &dash.video {
let video_qualities_and_codec_type = VideoQualityAndCodecType {
video_quality: media.id.into(),
codec_type: media.codecid.into(),
};
video_qualities_and_codec_types.push(video_qualities_and_codec_type);
}
}
for durl in &self.durls {
if !durl.durl.is_empty() {
let video_qualities_and_codec_type = VideoQualityAndCodecType {
video_quality: durl.quality.into(),
codec_type: self.video_codecid.into(),
};
video_qualities_and_codec_types.push(video_qualities_and_codec_type);
}
}
if let Some(medias) = self.dash.as_ref().and_then(|dash| dash.audio.as_ref()) {
for media in medias {
audio_qualities.push(media.id.into());
}
}
AvailableMediaFormats {
video_qualities_and_codec_types,
audio_qualities,
}
}
}
+45
View File
@@ -1,6 +1,11 @@
use serde::{Deserialize, Serialize};
use specta::Type;
use crate::types::{
audio_quality::AudioQuality,
available_media_formats::{AvailableMediaFormats, VideoQualityAndCodecType},
};
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
#[serde(default)]
pub struct CheeseMediaUrl {
@@ -122,3 +127,43 @@ pub struct DurlDetailInCheese {
pub order: i64,
pub md5: String,
}
impl CheeseMediaUrl {
pub fn to_get_available_media_formats_result(&self) -> AvailableMediaFormats {
let mut video_qualities_and_codec_types: Vec<VideoQualityAndCodecType> = Vec::new();
let mut audio_qualities: Vec<AudioQuality> = Vec::new();
if let Some(dash) = &self.dash {
for media in &dash.video {
let video_qualities_and_codec_type = VideoQualityAndCodecType {
video_quality: media.id.into(),
codec_type: media.codecid.into(),
};
video_qualities_and_codec_types.push(video_qualities_and_codec_type);
}
}
for durl in &self.durls {
if !durl.durl.is_empty() {
let video_qualities_and_codec_type = VideoQualityAndCodecType {
video_quality: durl.quality.into(),
codec_type: self.video_codecid.into(),
};
video_qualities_and_codec_types.push(video_qualities_and_codec_type);
}
}
if let Some(medias) = self.dash.as_ref().and_then(|dash| dash.audio.as_ref()) {
for media in medias {
audio_qualities.push(media.id.into());
}
}
AvailableMediaFormats {
video_qualities_and_codec_types,
audio_qualities,
}
}
}
@@ -0,0 +1,25 @@
use serde::{Deserialize, Serialize};
use specta::Type;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
pub enum GetAvailableMediaFormatsParams {
Normal(GetNormalAvailableMediaFormatsParams),
Bangumi(GetBangumiAvailableMediaFormatsParams),
Cheese(GetCheeseAvailableMediaFormatsParams),
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
pub struct GetNormalAvailableMediaFormatsParams {
pub bvid: String,
pub cid: i64,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
pub struct GetBangumiAvailableMediaFormatsParams {
pub cid: i64,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
pub struct GetCheeseAvailableMediaFormatsParams {
pub ep_id: i64,
}
+2
View File
@@ -1,4 +1,5 @@
pub mod audio_quality;
pub mod available_media_formats;
pub mod bangumi_follow_info;
pub mod bangumi_info;
pub mod bangumi_media_url;
@@ -8,6 +9,7 @@ pub mod codec_type;
pub mod create_download_task_params;
pub mod fav_folders;
pub mod fav_info;
pub mod get_available_media_formats_params;
pub mod get_bangumi_follow_info_params;
pub mod get_bangumi_info_params;
pub mod get_cheese_info_params;
+52
View File
@@ -1,6 +1,11 @@
use serde::{Deserialize, Serialize};
use specta::Type;
use crate::types::{
audio_quality::AudioQuality,
available_media_formats::{AvailableMediaFormats, VideoQualityAndCodecType},
};
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
#[serde(default)]
pub struct NormalMediaUrl {
@@ -103,3 +108,50 @@ pub struct SupportFormatInNormal {
pub struct PlayConf {
pub is_new_description: bool,
}
impl NormalMediaUrl {
pub fn to_get_available_media_formats_result(&self) -> AvailableMediaFormats {
let mut video_qualities_and_codec_types: Vec<VideoQualityAndCodecType> = Vec::new();
let mut audio_qualities: Vec<AudioQuality> = Vec::new();
for media in &self.dash.video {
let video_qualities_and_codec = VideoQualityAndCodecType {
video_quality: media.id.into(),
codec_type: media.codecid.into(),
};
video_qualities_and_codec_types.push(video_qualities_and_codec);
}
if !self.durl.is_empty() {
let video_qualities_and_codec = VideoQualityAndCodecType {
video_quality: self.quality.into(),
codec_type: self.video_codecid.into(),
};
video_qualities_and_codec_types.push(video_qualities_and_codec);
}
if let Some(medias) = &self.dash.audio {
for media in medias {
audio_qualities.push(media.id.into());
}
}
if let Some(medias) = &self.dash.dolby.audio {
for media in medias {
audio_qualities.push(media.id.into());
}
}
let flac = self.dash.flac.as_ref();
if let Some(media) = flac.and_then(|flac| flac.audio.as_ref()) {
audio_qualities.push(media.id.into());
}
AvailableMediaFormats {
video_qualities_and_codec_types,
audio_qualities,
}
}
}