Skip to content

Commit 3d8694c

Browse files
committed
feat: extract video thumbnails and display them during video loading to eliminate flicker
1 parent 42359ae commit 3d8694c

2 files changed

Lines changed: 44 additions & 0 deletions

File tree

crates/media-sort-gui/src/subscriptions/prefetch.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,45 @@ use crate::message::Message;
44

55
#[allow(dead_code)]
66
pub fn generate_thumbnail(path: &PathBuf) -> Vec<u8> {
7+
let is_video = if let Some(ext) = path.extension().and_then(|e| e.to_str()) {
8+
let ext_lower = ext.to_lowercase();
9+
ext_lower == "mp4" || ext_lower == "mkv" || ext_lower == "avi" || ext_lower == "mov" || ext_lower == "webm" || ext_lower == "wmv" || ext_lower == "flv"
10+
} else {
11+
false
12+
};
13+
14+
if is_video {
15+
if let Ok(mut player) = media_sort_backend::media::mpv_context::MpvContext::new() {
16+
if player.load_file(path).is_ok() {
17+
player.set_paused(true);
18+
let start_time = std::time::Instant::now();
19+
let mut loaded = false;
20+
while start_time.elapsed() < std::time::Duration::from_millis(500) {
21+
let (w, h) = player.get_video_size();
22+
if w > 0 && h > 0 {
23+
loaded = true;
24+
break;
25+
}
26+
std::thread::sleep(std::time::Duration::from_millis(10));
27+
}
28+
29+
if loaded {
30+
let render_w = 128;
31+
let render_h = 128;
32+
let mut buffer = vec![0u8; render_w * render_h * 4];
33+
if player.render_frame(render_w as i32, render_h as i32, &mut buffer).is_ok() {
34+
if let Some(rgba) = image::RgbaImage::from_raw(render_w as u32, render_h as u32, buffer) {
35+
let mut buf = std::io::Cursor::new(Vec::new());
36+
if rgba.write_to(&mut buf, image::ImageFormat::Png).is_ok() {
37+
return buf.into_inner();
38+
}
39+
}
40+
}
41+
}
42+
}
43+
}
44+
}
45+
746
if let Ok(img) = image::open(path) {
847
let thumbnail = img.thumbnail(128, 128);
948
let mut buf = std::io::Cursor::new(Vec::new());

crates/media-sort-gui/src/view/media_preview.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ pub fn media_preview_view(state: &AppState) -> Element<'_, Message> {
5353
.width(Length::Fill)
5454
.height(Length::Fill)
5555
.into()
56+
} else if let Some(thumb_handle) = state.thumbnail_cache.peek(&entry.path) {
57+
iced::widget::image(thumb_handle.clone())
58+
.width(Length::Fill)
59+
.height(Length::Fill)
60+
.into()
5661
} else {
5762
crate::widgets::video_canvas::video_canvas_view(entry.path.clone(), &state.l10n)
5863
};

0 commit comments

Comments
 (0)