fix: use VideoGenerator for video thumbnail generation - #7
Open
shaolun990905 wants to merge 2 commits into
Open
Conversation
- Route to VideoGenerator via GetGenerator() based on MIME type instead of calling GenerateThumbnails() directly which only supports images - Fix thumbnail upload MIME type to image/jpeg instead of source video MIME type - Add mimeTypeFromFilename() fallback when GetContentMetadata returns empty MIME type
GGGLHHH
reviewed
Mar 2, 2026
GGGLHHH
left a comment
Contributor
There was a problem hiding this comment.
Thanks for the fix on generator routing. I found two issues that should be addressed before merge:
- Incorrect thumbnail MIME type is hardcoded
- In
uploadResultsStep,MimeTypeis always set toimage/jpeg. - But output format is not always JPEG:
- image flow keeps source extension (
thumb.go) - PDF flow outputs
.png(pdf_generator.go)
- image flow keeps source extension (
- This can store wrong
Content-Typemetadata for uploaded objects. - Suggestion: derive MIME from
thumb.Path(or pass empty and let existingdetectMimehandle it).
- Unsupported MIME is swallowed by fallback to image generator
GetGeneratorerrors are always ignored and fallback goes toImageGenerator.- For truly unsupported types (e.g.
text/plain), this turns a clear permanent failure into an image decode failure, which may be classified as retryable. - Suggestion: only fallback to image generator when source MIME is empty; otherwise return the
unsupported MIMEerror directly.
Tests pass (go test ./..., go test -tags nats ./...), but these two behavior regressions should be fixed.
…types permanently
GGGLHHH
approved these changes
Mar 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
After uploading a video to a portfolio, the thumbnail generation service
(
simple-thumbnailer) failed silently. Investigation revealed two root causes:Root Cause 1: Wrong generator used for video files
handleJob in cmd/thumbnail-worker/main.go directly called
img.GenerateThumbnails(), which internally usesimaging.Open()— animage-only library that cannot handle video files. This caused the error:
open: image: unknown formatThe codebase already had a proper
img.GetGenerator(mimeType)function thatroutes to
VideoGenerator(FFmpeg-based frame extraction) forvideo/*MIMEtypes, but it was never called from the thumbnail worker entrypoint.
Root Cause 2: Thumbnails stored with wrong MIME type
Even when thumbnails were successfully generated,
UploadThumbnailObjectwascalled with
MimeType: source.MimeType(e.g.video/mp4), which caused thegenerated JPEG thumbnail to be stored in the database as a video file. The
preview API queries derived content with
status = processedand expectsimage MIME types for thumbnails, so it returned 404.
Root Cause 3: Empty MIME type fallback
FetchSourcecallsGetContentMetadatato determine the file's MIME type.If the metadata service returns an empty string (e.g. due to timing or
service issues), no generator could be selected and the worker fell back to
ImageGenerator, causing the same failure as Root Cause 1.Changes
img.GenerateThumbnails()withimg.GetGenerator(source.MimeType)tocorrectly dispatch to
VideoGeneratorfor video files andImageGeneratorfor images
UploadThumbnailObjectcall to useMimeType: "image/jpeg"andFileName: filepath.Base(thumb.Path)insteadof inheriting the source video's metadata
internal/upload/client.go: AddmimeTypeFromFilename()helper andapply it as a fallback when
GetContentMetadatareturns an empty MIME type,inferring type from file extension (
.mp4→video/mp4, etc.)Testing
Verified end-to-end: video upload → NATS job → FFmpeg frame extraction →
JPEG thumbnail uploaded with correct MIME type → preview API returns 200
with presigned S3 URL.
问题背景
视频上传到作品集后,缩略图生成服务(simple-thumbnailer)无法正常处理视频文件,
导致前端预览图一直返回 404 错误。经排查发现以下三个根本原因:
根本原因一:视频文件使用了错误的生成器
cmd/thumbnail-worker/main.go 中的 handleJob 直接调用了
img.GenerateThumbnails(),该函数内部使用imaging.Open(),这是一个仅支持图片格式的库,无法处理视频文件,导致报错:
open: image: unknown format代码库中已有
img.GetGenerator(mimeType)函数,可根据 MIME type 路由到VideoGenerator(基于 FFmpeg 提取视频帧),但 thumbnail worker 入口从未调用它。根本原因二:缩略图以错误的 MIME type 存储
即使缩略图文件成功生成,
UploadThumbnailObject调用时传入的是MimeType: source.MimeType(如video/mp4),导致生成的 JPEG 缩略图在数据库中被标记为视频文件。Preview API 查询时要求衍生内容状态为
processed且类型为图片,因此无法匹配,返回 404。
根本原因三:MIME type 为空时缺少兜底处理
FetchSource通过GetContentMetadata获取文件 MIME type。若接口返回空字符串(如服务时序问题),则无法选择正确的生成器,最终 fallback 到
ImageGenerator,与根本原因一产生相同的失败。
修改内容
img.GenerateThumbnails()改为通过
img.GetGenerator(source.MimeType)动态选择生成器,视频文件路由到VideoGenerator,图片文件路由到ImageGeneratorUploadThumbnailObject调用,将 MIME type 改为
image/jpeg,文件名改为缩略图文件自身的名称,不再继承原始视频的元数据
internal/upload/client.go:新增mimeTypeFromFilename()辅助函数,当
GetContentMetadata返回空 MIME type 时,通过文件扩展名推断类型(如
.mp4→video/mp4)验证
端到端验证通过:视频上传 → NATS 消息触发任务 → FFmpeg 提取视频帧 →
JPEG 缩略图以正确 MIME type 上传 → Preview API 返回 200 及 S3 预签名 URL。