From a257f50a9f752919729bcf3aa3358491ff5edcad Mon Sep 17 00:00:00 2001 From: dec05eba Date: Thu, 21 Dec 2023 18:23:53 +0100 Subject: Fix thumbnails for broken videos (unable to seek) --- include/FileAnalyzer.hpp | 3 --- src/FileAnalyzer.cpp | 14 +++++++------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/include/FileAnalyzer.hpp b/include/FileAnalyzer.hpp index 52cc328..47b02d7 100644 --- a/include/FileAnalyzer.hpp +++ b/include/FileAnalyzer.hpp @@ -44,9 +44,6 @@ namespace QuickMedia { bool is_video_ext(const char *ext); bool is_music_ext(const char *ext); - // Set |width| or |height| to 0 to disable scaling. - // TODO: Make this async - bool video_get_start_frame(const FileAnalyzer &file, const char *destination_path, int width = 0, int height = 0); // Set |width| or |height| to 0 to disable scaling. // TODO: Make this async bool video_get_middle_frame(const FileAnalyzer &file, const char *destination_path, int width = 0, int height = 0); diff --git a/src/FileAnalyzer.cpp b/src/FileAnalyzer.cpp index 9efdc52..4deb8c3 100644 --- a/src/FileAnalyzer.cpp +++ b/src/FileAnalyzer.cpp @@ -144,7 +144,7 @@ namespace QuickMedia { || strcase_equals(ext, ".mid"); } - bool video_get_frame(const FileAnalyzer &file, const char *destination_path, int width, int height, int seconds) { + static bool video_get_frame(const FileAnalyzer &file, const char *destination_path, int width, int height, int seconds, bool fallback_first_frame) { Path destination_path_tmp = destination_path; destination_path_tmp.append(".tmp.jpg"); // TODO: .png, but the below code also needs to be changed for that @@ -162,6 +162,11 @@ namespace QuickMedia { fprintf(stderr, "Failed to execute ffmpeg, maybe its not installed?\n"); return false; } + + // Some corrupted videos (unseekable) can fail but ffmpeg doesn't report an error, it only reports a warning. + // In such cases the output file is not created and we can then instead try to get the first video frame instead + if(fallback_first_frame && get_file_type(destination_path_tmp) == FileType::FILE_NOT_FOUND) + return video_get_frame(file, destination_path, width, height, 0, false); } else { const char *program_args[] = { "ffmpeg", "-y", "-v", "quiet", "-ss", seconds_str, "-i", file.get_filepath().c_str(), "-frames:v", "1", "--", destination_path_tmp.data.c_str(), nullptr }; if(exec_program(program_args, nullptr, nullptr, allowed_exit_status, 2) != 0) { @@ -173,14 +178,9 @@ namespace QuickMedia { return rename_atomic(destination_path_tmp.data.c_str(), destination_path) == 0; } - bool video_get_start_frame(const FileAnalyzer &file, const char *destination_path, int width, int height) { - const int start_seconds = std::max(0.0, std::min(3.0, file.get_duration_seconds().value_or(0.0) - 1.0)); - return video_get_frame(file, destination_path, width, height, start_seconds); - } - bool video_get_middle_frame(const FileAnalyzer &file, const char *destination_path, int width, int height) { const int middle_seconds = file.get_duration_seconds().value_or(0.0) / 2.0; - return video_get_frame(file, destination_path, width, height, middle_seconds); + return video_get_frame(file, destination_path, width, height, middle_seconds, true); } // TODO: Remove dependency on ffprobe -- cgit v1.2.3