33#include " render_pipeline.h"
44
55namespace {
6- size_t get_seek_start_frame (const std::filesystem::path& input_path, float seek) {
7- auto video_info = u::get_video_info (input_path);
6+ constexpr int FRAMES_NEEDED_FOR_VSPIPE_TO_NOT_POO_ITSELF =
7+ 3 ; // need some buffer of frames so something actually renders out. idk how to get a proper value for this.
8+ // @todo: make sure this doesnt ever fail (set config preview seek = 1 and try lots of diff vids and configs,
9+ // make sure preview never fails to render)
10+
11+ size_t get_seek_start_frame (const BlurSettings& settings, const u::VideoInfo& video_info, float seek) {
812 if (!video_info.has_video_stream || video_info.fps_num <= 0 || video_info.fps_den <= 0 ||
913 video_info.duration <= 0 .f )
1014 return 0 ;
1115
16+ double ffmpeg_required_extra_time = 1 .f / settings.blur_output_fps ; // see -ss below
1217 double fps = static_cast <double >(video_info.fps_num ) / video_info.fps_den ;
13- auto total_frames = static_cast <size_t >(video_info.duration * fps);
1418
15- return std::min (
16- static_cast <size_t >(std::clamp (seek, 0 .f , 1 .f ) * total_frames), total_frames - 1
17- ); // cap at total_frames - 1 cause otherwise start will be end and vspipe will error (needs at least 1 frame)
19+ size_t total_frames = static_cast <size_t >(video_info.duration * fps);
20+
21+ size_t total_usable_frames = static_cast <size_t >(std::max (
22+ 0.0 , ((video_info.duration - ffmpeg_required_extra_time) * fps) - FRAMES_NEEDED_FOR_VSPIPE_TO_NOT_POO_ITSELF
23+ ));
24+
25+ size_t start_frame = static_cast <size_t >(std::clamp (seek, 0 .f , 1 .f ) * total_frames);
26+ size_t offset = total_frames > total_usable_frames ? total_frames - total_usable_frames : 0 ;
27+
28+ return offset < start_frame ? start_frame - offset : 0 ;
1829 }
1930}
2031
@@ -35,14 +46,11 @@ tl::expected<rendering::FrameRenderResult, std::variant<std::string, rendering::
3546 if (!merged_settings)
3647 return tl::unexpected (merged_settings.error ());
3748
38- auto vspipe_args = detail::build_vspipe_base_args (input_path, *merged_settings );
49+ auto video_info = u::get_video_info (input_path);
3950
40- if (seek > 0 .f ) {
41- size_t start_frame = get_seek_start_frame (input_path, seek);
42- if (start_frame > 0 ) {
43- vspipe_args.insert (vspipe_args.end () - 2 , { " -a" , std::format (" start={}" , start_frame) });
44- }
45- }
51+ auto vspipe_args = detail::build_vspipe_video_args (
52+ input_path, *merged_settings, video_info, seek > 0 .f ? get_seek_start_frame (settings, video_info, seek) : 0
53+ );
4654
4755 RenderCommands commands = {
4856 .vspipe_video = std::move (vspipe_args),
@@ -51,11 +59,12 @@ tl::expected<rendering::FrameRenderResult, std::variant<std::string, rendering::
5159 " -hide_banner" ,
5260 " -stats" ,
5361 " -i" , " -" ,
62+ " -ss" , std::to_string (1 .f / settings.blur_output_fps ), // skip ahead a frame, likely need a frame for frames to start being blended @todo: revisit if i ever change that behaviour (first frame of video not being blurred properly thing)
5463 " -map" , " 0:v" ,
55- " -vframes" , " 1" ,
64+ " -frames:v" , " 1" ,
65+ " -c:v" , " mjpeg" ,
5666 " -q:v" , " 2" ,
5767 " -f" , " image2pipe" ,
58- " -vcodec" , " mjpeg" ,
5968 " -" ,
6069 },
6170 };
0 commit comments