Skip to content

Commit 1eda453

Browse files
committed
[*] refactor video editor
1 parent 6d566f7 commit 1eda453

File tree

4 files changed

+47
-22
lines changed

4 files changed

+47
-22
lines changed

lib/video-editor/src/tracks/decode_video.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ fn extract_segment_frames_worker(
340340
let relative_timeline_offset = relative_segment_timeline_offset_start
341341
+ output_converter.frame_to_duration(received_count);
342342

343-
let filtered_frame = apply_filter_to_frame(
343+
let filtered_frame = apply_filter_to_frame_for_video(
344344
&config_clone,
345345
frame,
346346
from_seg.clone(),
@@ -408,7 +408,7 @@ fn send_empty_frame(
408408
Ok(())
409409
}
410410

411-
fn apply_filter_to_frame(
411+
fn apply_filter_to_frame_for_video(
412412
config: &DecodeVideoConfig,
413413
frame: VideoImage,
414414
segment: Arc<Segment>,
@@ -757,10 +757,7 @@ fn render_image_segment(
757757
relative_timeline_offset: frame_offset,
758758
};
759759
if let Err(e) = filter.inner.apply(&mut ui_data) {
760-
log::warn!(
761-
"Apply image filter: `{}` failed: {e}",
762-
filter.inner.name()
763-
);
760+
log::warn!("Apply image filter: `{}` failed: {e}", filter.inner.name());
764761
}
765762
image = ui_data.frames.pop().unwrap_or(VideoImage::Empty);
766763
image_for_composite = None;
@@ -773,10 +770,7 @@ fn render_image_segment(
773770
relative_timeline_offset: frame_offset,
774771
};
775772
if let Err(e) = filter.inner.apply(&mut composite_data) {
776-
log::warn!(
777-
"Apply image filter: `{}` failed: {e}",
778-
filter.inner.name()
779-
);
773+
log::warn!("Apply image filter: `{}` failed: {e}", filter.inner.name());
780774
}
781775
image_for_composite = composite_data.frames.pop();
782776
}

lib/video-editor/src/tracks/video_track.rs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -649,32 +649,54 @@ impl Iterator for UnifiedVideoTracksCompositorIterator {
649649
}
650650
}
651651

652-
// 将前景帧按左上角对齐合成到背景帧上(简单的 Alpha 混合)
652+
// 将前景帧合成到背景帧上(居中对齐,简单的 Alpha 混合)
653653
// alpha == 255: 直接覆盖背景像素
654654
// alpha > 0: Alpha 混合前景和背景
655655
// alpha == 0: 完全透明,保持背景不变
656656
pub fn composite_frame(composited: &mut RgbaImage, foreground: &VideoImage) {
657657
match foreground {
658658
VideoImage::Empty => (),
659659
VideoImage::Image { buffer } => {
660-
let fg_width = buffer.width().min(composited.width());
661-
let fg_height = buffer.height().min(composited.height());
660+
let fg_width = buffer.width();
661+
let fg_height = buffer.height();
662+
let bg_width = composited.width();
663+
let bg_height = composited.height();
664+
665+
// Center the foreground if smaller than background
666+
let x_offset = if fg_width < bg_width {
667+
(bg_width - fg_width) / 2
668+
} else {
669+
0
670+
};
671+
let y_offset = if fg_height < bg_height {
672+
(bg_height - fg_height) / 2
673+
} else {
674+
0
675+
};
662676

663-
for y in 0..fg_height {
664-
for x in 0..fg_width {
677+
// Clamp dimensions for iteration
678+
let iter_width = fg_width.min(bg_width);
679+
let iter_height = fg_height.min(bg_height);
680+
681+
for y in 0..iter_height {
682+
for x in 0..iter_width {
665683
let fg_pixel = buffer.get_pixel(x, y);
666684
let fg_alpha = fg_pixel[3];
667685

686+
// Apply pixel at centered position
687+
let bg_x = x_offset + x;
688+
let bg_y = y_offset + y;
689+
668690
if fg_alpha == 255 {
669691
// 不透明:直接覆盖
670-
let bg_pixel = composited.get_pixel_mut(x, y);
692+
let bg_pixel = composited.get_pixel_mut(bg_x, bg_y);
671693
bg_pixel[0] = fg_pixel[0];
672694
bg_pixel[1] = fg_pixel[1];
673695
bg_pixel[2] = fg_pixel[2];
674696
bg_pixel[3] = fg_pixel[3];
675697
} else if fg_alpha > 0 {
676698
// 半透明:Alpha 混合
677-
let bg_pixel = composited.get_pixel_mut(x, y);
699+
let bg_pixel = composited.get_pixel_mut(bg_x, bg_y);
678700
let alpha = fg_alpha as f32 / 255.0;
679701
let inv_alpha = 1.0 - alpha;
680702

todo.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## 问题
2-
- 联动模式下,拖拽segment左边缘是保持左边缘位置不变,但是源文件的开始时间改变,现在是改变segment的时长。
3-
- filter 取消选中,黑屏,应该显示preveiw图片
2+
- playlist 和 library thumbnail预览图片变形了
3+
- filter没有参数时,下面呃呃详情面板应该显示没有图片
44

55
## 待验证
66
- 视频轨道分离字幕

wayshot/src/logic/video_editor/conversion.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use super::command::with_history_manager;
12
use crate::slint_generatedAppWindow::{
23
AudioChannels as UIAudioChannels, AudioFormat as UIAudioFormat,
34
AudioSampleRate as UIAudioSampleRate, FilterType as UIFilterType, Fps as UIFps,
@@ -23,8 +24,8 @@ use video_editor::{
2324
commands::filter::FilterType,
2425
export::{AudioExportFormat, SubtitleFormat},
2526
filters::{
26-
AudioFilter, AudioFilterWrapper, ImageFilterWrapper, SubtitleFilter,
27-
SubtitleFilterWrapper, VideoFilter, VideoFilterWrapper,
27+
AudioFilter, AudioFilterWrapper, ImageFilterWrapper, SubtitleFilter, SubtitleFilterWrapper,
28+
VideoFilter, VideoFilterWrapper,
2829
audio::{
2930
CompressorFilter, FadeInFilter as AudioFadeInFilter,
3031
FadeOutFilter as AudioFadeOutFilter, GainFilter, LimiterFilter, MuteLeftFilter,
@@ -664,11 +665,19 @@ impl From<UIFilterType> for FilterType {
664665
pub fn layer_frame_to_ui(layer: &LayerFrame) -> Option<UIVideoEditorLayerImage> {
665666
match &layer.image {
666667
VideoImage::Image { buffer, .. } => {
668+
let is_image_track = with_history_manager(|state| {
669+
state
670+
.tracks_manager
671+
.get(layer.track_index)
672+
.map(|t| t.is_image())
673+
.unwrap_or(false)
674+
});
675+
667676
let transform: UITransformDetail = layer
668677
.from_segment
669678
.as_ref()
670679
.and_then(|(_, segment)| {
671-
if segment.metadata.is_image() {
680+
if is_image_track {
672681
segment
673682
.image_filters
674683
.iter()

0 commit comments

Comments
 (0)