Add youtube.rs for YouTube support

This commit is contained in:
2026-03-19 00:32:39 +08:00
parent 3acc36f648
commit f5a117c878

62
src/input/youtube.rs Normal file
View File

@@ -0,0 +1,62 @@
//! YouTube URL 輸入
use anyhow::Result;
use std::process::Command;
pub struct YouTubeInput {
url: Option<String>,
title: Option<String>,
duration: Option<u64>,
}
impl YouTubeInput {
pub fn new() -> Self {
Self {
url: None,
title: None,
duration: None,
}
}
pub fn parse(&mut self, url: &str) -> Result<String> {
if !Self::is_youtube_url(url) {
anyhow::bail!("Not a valid YouTube URL");
}
self.url = Some(url.to_string());
let info = self.get_video_info(url)?;
self.title = Some(info.0);
self.duration = Some(info.1);
Ok(url.to_string())
}
fn is_youtube_url(url: &str) -> bool {
url.contains("youtube.com") || url.contains("youtu.be")
}
fn get_video_info(&self, url: &str) -> Result<(String, u64)> {
let output = Command::new("yt-dlp")
.args(["--dump-json", "--no-download", url])
.output()?;
if !output.status.success() {
anyhow::bail!("Failed to get video info");
}
let json: serde_json::Value = serde_json::from_slice(&output.stdout)?;
let title = json["title"].as_str().unwrap_or("Unknown").to_string();
let duration = json["duration"].as_u64().unwrap_or(0);
Ok((title, duration))
}
pub fn get_title(&self) -> Option<&str> {
self.title.as_deref()
}
pub fn get_duration(&self) -> Option<u64> {
self.duration
}
}