use std::path::PathBuf;
use lingxia_platform::traits::media_runtime::{
CompressImageRequest as PlatformCompressImageRequest,
CompressVideoRequest as PlatformCompressVideoRequest,
ExtractVideoThumbnailRequest as PlatformExtractVideoThumbnailRequest, MediaRuntime,
VideoCompressQuality as PlatformVideoCompressQuality,
};
use serde::{Deserialize, Serialize};
pub use lingxia_media::{
FrameSink, StreamError, StreamProvider, StreamSession, get_stream_provider,
register_stream_provider, register_stream_seek_callback, seek_stream_session,
unregister_stream_seek_callback,
};
pub use lingxia_service::media::{
CameraFacing, ChooseMediaMode, ChooseMediaRequest, MediaKind, MediaObjectFit, MediaQuality,
MediaSource, PreviewMediaAdvance, PreviewMediaItem, PreviewMediaRequest, SaveMediaRequest,
ScanCodeRequest, ScanType,
};
pub async fn choose(request: ChooseMediaRequest) -> crate::Result<String> {
let runtime = crate::runtime::platform()?;
lingxia_service::media::choose_media(&*runtime, request)
.await
.map_err(Into::into)
}
pub fn preview(request: PreviewMediaRequest) -> crate::Result<()> {
let runtime = crate::runtime::platform()?;
lingxia_service::media::preview_media(&*runtime, request).map_err(Into::into)
}
pub fn cancel_preview(callback_id: u64) -> crate::Result<()> {
let runtime = crate::runtime::platform()?;
lingxia_service::media::cancel_preview(&*runtime, callback_id).map_err(Into::into)
}
pub async fn scan(request: ScanCodeRequest) -> crate::Result<String> {
let runtime = crate::runtime::platform()?;
lingxia_service::media::scan_code(&*runtime, request)
.await
.map_err(Into::into)
}
pub async fn save_image_to_photo_library(request: SaveMediaRequest) -> crate::Result<()> {
let runtime = crate::runtime::platform()?;
lingxia_service::media::save_image_to_photos_album(&*runtime, request)
.await
.map_err(Into::into)
}
pub async fn save_video_to_photo_library(request: SaveMediaRequest) -> crate::Result<()> {
let runtime = crate::runtime::platform()?;
lingxia_service::media::save_video_to_photos_album(&*runtime, request)
.await
.map_err(Into::into)
}
#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct ImageInfo {
pub width: u32,
pub height: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub mime_type: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CompressImage {
pub source_path: String,
pub quality: u8,
#[serde(default)]
pub max_width: Option<u32>,
#[serde(default)]
pub max_height: Option<u32>,
pub output_path: String,
}
#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct CompressedImage {
pub path: PathBuf,
}
#[derive(Debug, Clone, Serialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct VideoInfo {
pub width: u32,
pub height: u32,
pub duration_ms: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub rotation: Option<u16>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bitrate: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub fps: Option<f32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mime_type: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ExtractVideoThumbnail {
pub source_path: String,
pub output_path: String,
#[serde(default)]
pub max_width: Option<u32>,
#[serde(default)]
pub max_height: Option<u32>,
#[serde(default)]
pub time_ms: Option<u64>,
pub quality: u8,
}
#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct VideoThumbnail {
pub path: PathBuf,
pub width: u32,
pub height: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub mime_type: Option<String>,
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum VideoQuality {
Low,
Medium,
High,
}
impl From<VideoQuality> for PlatformVideoCompressQuality {
fn from(value: VideoQuality) -> Self {
match value {
VideoQuality::Low => PlatformVideoCompressQuality::Low,
VideoQuality::Medium => PlatformVideoCompressQuality::Medium,
VideoQuality::High => PlatformVideoCompressQuality::High,
}
}
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CompressVideo {
pub source_path: String,
#[serde(default)]
pub quality: Option<VideoQuality>,
#[serde(default)]
pub bitrate_kbps: Option<u32>,
#[serde(default)]
pub fps: Option<u32>,
#[serde(default)]
pub resolution_ratio: Option<f32>,
pub output_path: String,
}
#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct CompressedVideo {
pub path: PathBuf,
pub width: u32,
pub height: u32,
pub duration_ms: u64,
pub size: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub mime_type: Option<String>,
}
pub fn image_info(path: &str) -> crate::Result<ImageInfo> {
let info = crate::runtime::platform()?
.get_image_info(path)
.map_err(crate::Error::from)?;
Ok(ImageInfo {
width: info.width,
height: info.height,
mime_type: info.mime_type,
})
}
pub fn compress_image(input: CompressImage) -> crate::Result<CompressedImage> {
let request = PlatformCompressImageRequest {
source_uri: input.source_path,
quality: input.quality,
max_width: input.max_width,
max_height: input.max_height,
output_path: PathBuf::from(input.output_path),
};
let path = crate::runtime::platform()?
.compress_image(&request)
.map_err(crate::Error::from)?;
Ok(CompressedImage { path })
}
pub fn video_info(path: &str) -> crate::Result<VideoInfo> {
let info = crate::runtime::platform()?
.get_video_info(path)
.map_err(crate::Error::from)?;
Ok(VideoInfo {
width: info.width,
height: info.height,
duration_ms: info.duration_ms,
rotation: info.rotation,
bitrate: info.bitrate,
fps: info.fps,
mime_type: info.mime_type,
})
}
pub fn extract_video_thumbnail(input: ExtractVideoThumbnail) -> crate::Result<VideoThumbnail> {
let request = PlatformExtractVideoThumbnailRequest {
source_uri: input.source_path,
output_path: PathBuf::from(input.output_path),
max_width: input.max_width,
max_height: input.max_height,
time_ms: input.time_ms,
quality: input.quality,
};
let thumb = crate::runtime::platform()?
.extract_video_thumbnail(&request)
.map_err(crate::Error::from)?;
Ok(VideoThumbnail {
path: thumb.path,
width: thumb.width,
height: thumb.height,
mime_type: thumb.mime_type,
})
}
pub fn compress_video(input: CompressVideo) -> crate::Result<CompressedVideo> {
let request = PlatformCompressVideoRequest {
source_uri: input.source_path,
quality: input.quality.map(Into::into),
bitrate_kbps: input.bitrate_kbps,
fps: input.fps,
resolution_ratio: input.resolution_ratio,
output_path: PathBuf::from(input.output_path),
};
let result = crate::runtime::platform()?
.compress_video(&request)
.map_err(crate::Error::from)?;
Ok(CompressedVideo {
path: result.path,
width: result.width,
height: result.height,
duration_ms: result.duration_ms,
size: result.size,
mime_type: result.mime_type,
})
}