Files
quyun-v2/docs/plan.md

108 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Implementation Plan: p3-17-media-processing-s3
**Branch**: `[p3-17-media-processing-s3]` | **Date**: 2026-02-04 | **Spec**: `docs/todo_list.md#17`
**Input**: P3-17 “媒体处理管线适配对象存储S3/MinIO” + user request to extract a cover from `fixtures/demo.mp4` via ffmpeg.
## Summary
Adapt the media processing worker to support S3/MinIO storage by downloading source media to a temp directory, running ffmpeg to generate a cover image, uploading derived assets via the storage provider, and preserving the existing local filesystem path. Include fixture-based verification using `fixtures/demo.mp4`.
## Technical Context
**Language/Version**: Go 1.x (project standard)
**Primary Dependencies**: River (jobs), MinIO SDK (S3 compatible), Fiber
**Storage**: PostgreSQL + local filesystem / S3-compatible storage
**Testing**: `go test` (service/job tests), ffmpeg CLI for fixture validation
**Target Platform**: Linux server
**Project Type**: Web application (backend + frontend, backend-only changes)
**Performance Goals**: N/A (processing path only)
**Constraints**: Preserve local storage behavior; do not edit generated files; follow `backend/llm.txt`; ensure temp files are cleaned
**Scale/Scope**: Media processing worker + storage provider only
## Constitution Check
- Follow `backend/llm.txt` conventions and Chinese comments for business logic.
- Do not edit generated files (`*.gen.go`, `backend/docs/docs.go`).
- Keep controller thin; changes limited to jobs/services/providers.
- Preserve local provider behavior; add S3 path without regression.
## Project Structure
### Documentation (this feature)
```text
docs/
└── plan.md # This plan
```
### Source Code (repository root)
```text
backend/
├── app/
│ ├── jobs/
│ │ ├── media_process_job.go
│ │ └── args/media_asset_process.go
│ └── services/
│ └── common.go
└── providers/
└── storage/provider.go
fixtures/
└── demo.mp4
```
**Structure Decision**: Web application backend; scope limited to media processing worker and storage provider integration.
## Plan Phases
1. **Design & plumbing**: Define temp file conventions and storage download API for S3/local.
2. **Implementation**: Add S3 processing flow to worker and cover asset registration; keep local path intact.
3. **Verification**: Add tests (or integration checks) and run fixture-based ffmpeg validation.
## Tasks
1. **Define storage download interface**
- Add a storage provider helper to download an object to a local temp file (local: copy from `LocalPath/objectKey` without rename; S3: `FGetObject`).
- Ensure helper never mutates/deletes the source object, creates parent dirs for destination, and overwrites the destination if it already exists.
- Ensure API is used by jobs without leaking provider-specific logic.
2. **Adapt `MediaProcessWorker` for S3/MinIO**
- For non-local providers, download the source object into a temp directory.
- Run ffmpeg to extract a cover image from the temp file.
- Upload the cover via `storage.PutObject` and register the derived media asset.
- Ensure temp directories/files are cleaned on success or failure.
3. **Update cover asset registration**
- For non-local providers, avoid filesystem rename; upload via storage provider and keep object key conventions.
- Use `storage.PutObject(ctx, objectKey, coverTempPath, "image/jpeg")`, then cleanup temp files/dirs.
- Keep local path move behavior unchanged.
4. **Add tests / verification hooks**
- Add a job/service test for S3 path (gated by MinIO env if needed).
- Keep/extend local path test to ensure no regression.
- Validate `fixtures/demo.mp4` can produce a cover with ffmpeg.
## Dependencies
- Task 1 must complete before Task 2 (worker needs download API).
- Task 2 must complete before Task 3 (cover registration requires new flow).
- Task 4 depends on Task 2 & 3 (tests rely on updated pipeline).
## Acceptance Criteria
- **Local path unchanged**: `MediaProcessWorker` still generates a cover image for local provider when ffmpeg is available.
- **S3/MinIO path works**: For `Storage.Type = s3`, the worker downloads source media, generates cover via ffmpeg, uploads cover to bucket, and creates a derived `media_assets` record with correct object key.
- **Fixture validation**: `ffmpeg -y -i fixtures/demo.mp4 -ss 00:00:00.000 -vframes 1 /tmp/demo_cover.jpg` succeeds locally and produces a non-empty file.
- **S3/MinIO test config**: tests load Storage config with `Type=s3`, `Endpoint`, `AccessKey`, `SecretKey`, `Bucket`, `PathStyle` (true for MinIO).
- **Automated checks** (to be added in this phase):
- `go test ./backend/app/jobs -run TestMediaProcessWorkerS3 -count=1` passes (with S3/MinIO config loaded).
- `go test ./backend/app/jobs -run TestMediaProcessWorkerLocal -count=1` passes.
## Risks
- **ffmpeg not installed**: Worker should detect and log; processing should fail gracefully.
- **Temp storage pressure**: Large media downloads may exceed disk; ensure cleanup on all paths.
- **S3 connectivity/transient errors**: Add retry or error propagation to avoid silent failures.
- **Access policies**: Misconfigured bucket policies may prevent download/upload; surface clear errors.