fix ig thumbnail

This commit is contained in:
Julian Freeman
2025-12-30 09:13:12 -04:00
parent 63648f9d7c
commit 05887fd7a3
5 changed files with 62 additions and 0 deletions

1
src-tauri/Cargo.lock generated
View File

@@ -3974,6 +3974,7 @@ name = "stream-capture"
version = "1.1.0" version = "1.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"base64 0.22.1",
"chrono", "chrono",
"futures-util", "futures-util",
"regex", "regex",

View File

@@ -19,6 +19,7 @@ tauri-plugin-dialog = "2"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
serde_json = "1" serde_json = "1"
reqwest = { version = "0.12", features = ["json", "rustls-tls", "stream"] } reqwest = { version = "0.12", features = ["json", "rustls-tls", "stream"] }
base64 = "0.22"
tokio = { version = "1", features = ["full"] } tokio = { version = "1", features = ["full"] }
anyhow = "1.0" anyhow = "1.0"
chrono = { version = "0.4", features = ["serde"] } chrono = { version = "0.4", features = ["serde"] }

View File

@@ -49,6 +49,28 @@ pub fn get_ffmpeg_version(app: AppHandle) -> Result<String, String> {
binary_manager::get_ffmpeg_version(&app).map_err(|e| e.to_string()) binary_manager::get_ffmpeg_version(&app).map_err(|e| e.to_string())
} }
#[tauri::command]
pub async fn fetch_image(url: String) -> Result<String, String> {
use base64::{Engine as _, engine::general_purpose};
let client = reqwest::Client::new();
let res = client.get(&url)
.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
.send()
.await
.map_err(|e| e.to_string())?;
let bytes = res.bytes().await.map_err(|e| e.to_string())?;
// Convert to base64
let b64 = general_purpose::STANDARD.encode(&bytes);
// Simple heuristic for mime type
let mime = if url.to_lowercase().ends_with(".png") { "image/png" } else { "image/jpeg" };
Ok(format!("data:{};base64,{}", mime, b64))
}
#[tauri::command] #[tauri::command]
pub async fn fetch_metadata(app: AppHandle, url: String, parse_mix_playlist: bool) -> Result<downloader::MetadataResult, String> { pub async fn fetch_metadata(app: AppHandle, url: String, parse_mix_playlist: bool) -> Result<downloader::MetadataResult, String> {
downloader::fetch_metadata(&app, &url, parse_mix_playlist).await.map_err(|e| e.to_string()) downloader::fetch_metadata(&app, &url, parse_mix_playlist).await.map_err(|e| e.to_string())

View File

@@ -17,6 +17,7 @@ pub fn run() {
commands::get_ytdlp_version, commands::get_ytdlp_version,
commands::get_quickjs_version, commands::get_quickjs_version,
commands::get_ffmpeg_version, commands::get_ffmpeg_version,
commands::fetch_image,
commands::fetch_metadata, commands::fetch_metadata,
commands::start_download, commands::start_download,
commands::get_settings, commands::get_settings,

View File

@@ -61,6 +61,38 @@ watch(() => analysisStore.options.is_audio_only, () => {
analysisStore.options.output_format = 'original' analysisStore.options.output_format = 'original'
}) })
async function processThumbnail(url: string | undefined): Promise<string | undefined> {
if (!url) return undefined;
// Check if it's an Instagram URL or similar that needs proxying
if (url.includes('instagram.com') || url.includes('fbcdn.net') || url.includes('cdninstagram.com')) {
try {
return await invoke<string>('fetch_image', { url });
} catch (e) {
console.warn('Thumbnail fetch failed, falling back to URL', e);
return url;
}
}
return url;
}
async function processMetadataThumbnails(metadata: any) {
if (!metadata) return;
// Process single video thumbnail
if (metadata.thumbnail) {
metadata.thumbnail = await processThumbnail(metadata.thumbnail);
}
// Process playlist entries
if (metadata.entries && Array.isArray(metadata.entries)) {
await Promise.all(metadata.entries.map(async (entry: any) => {
if (entry.thumbnail) {
entry.thumbnail = await processThumbnail(entry.thumbnail);
}
}));
}
}
async function analyze() { async function analyze() {
if (!analysisStore.url) return if (!analysisStore.url) return
analysisStore.loading = true analysisStore.loading = true
@@ -122,6 +154,9 @@ async function analyze() {
throw new Error("所有链接解析失败或均为播放列表。"); throw new Error("所有链接解析失败或均为播放列表。");
} }
// Process thumbnails for batch results
await Promise.all(results.map(r => processMetadataThumbnails(r)));
// Construct synthetic playlist // Construct synthetic playlist
analysisStore.metadata = { analysisStore.metadata = {
id: 'batch_download_' + Date.now(), id: 'batch_download_' + Date.now(),
@@ -155,6 +190,8 @@ async function analyze() {
const res = await invoke<any>('fetch_metadata', { url: urlToScan, parseMixPlaylist: parseMix }) const res = await invoke<any>('fetch_metadata', { url: urlToScan, parseMixPlaylist: parseMix })
await processMetadataThumbnails(res);
// Initialize selected state for playlist entries // Initialize selected state for playlist entries
if (res.entries) { if (res.entries) {
res.entries = res.entries.map((e: any) => ({ ...e, selected: true })) res.entries = res.entries.map((e: any) => ({ ...e, selected: true }))