feat(render #36): real per-tier output height (360/540/720/1080/4K)
Build backend images / build content-svc (push) Failing after 50s
Build backend images / build file-svc (push) Failing after 57s
Build backend images / build gateway (push) Failing after 50s
Build backend images / build identity-svc (push) Failing after 58s
Build backend images / build notification-svc (push) Failing after 48s
Build backend images / build render-svc (push) Failing after 53s
Build backend images / build studio-svc (push) Failing after 1m2s

r_height was hardcoded 1080. render-svc now derives r_height from the resolution
(ResolutionHeight) on job create; node-agent ffmpeg downscales to the tier height
(scale=-2:H). Quality picker now actually changes output size.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-07 04:35:14 +03:30
parent c6766b18a1
commit bccebbd006
2 changed files with 49 additions and 5 deletions
+27 -3
View File
@@ -187,7 +187,25 @@ func ffmpegPath() string {
// transcodeToMP4 converts a lossless AE render (AVI/MOV) to a web-playable H.264
// MP4 using ffmpeg. Returns the .mp4 path. Errors if ffmpeg is unavailable.
func transcodeToMP4(ctx context.Context, src, requested string) (string, error) {
// resolutionHeight maps a quality-tier label to its output height (mirrors render-svc).
func resolutionHeight(resolution string) int {
switch strings.ToLower(strings.TrimSpace(resolution)) {
case "360p":
return 360
case "540p":
return 540
case "720p":
return 720
case "1080p", "fullhd":
return 1080
case "4k", "2160p":
return 2160
default:
return 0 // unknown → no scaling
}
}
func transcodeToMP4(ctx context.Context, src, requested string, height int) (string, error) {
ff := ffmpegPath()
if ff == "" {
return "", fmt.Errorf("ffmpeg not found (set FFMPEG_PATH or place ffmpeg.exe next to the agent)")
@@ -196,10 +214,16 @@ func transcodeToMP4(ctx context.Context, src, requested string) (string, error)
args := []string{
"-y", "-i", src,
"-c:v", "libx264", "-preset", "medium", "-crf", "20", "-pix_fmt", "yuv420p",
}
// Downscale (or up) to the selected quality tier. -2 keeps width even & aspect.
if height > 0 {
args = append(args, "-vf", fmt.Sprintf("scale=-2:%d", height))
}
args = append(args,
"-c:a", "aac", "-b:a", "192k",
"-movflags", "+faststart",
dst,
}
)
log.Printf("[ffmpeg] %s %v", ff, args)
cmd := exec.CommandContext(ctx, ff, args...)
cmd.Stdout = os.Stdout
@@ -281,7 +305,7 @@ func aeRender(ctx context.Context, aePath string, job *Job, outputPath string, o
}
// Transcode the lossless render → H.264 MP4 (much smaller, web-playable).
_ = onProgress(ctx, 92, "Transcoding to MP4…")
mp4, terr := transcodeToMP4(ctx, actual, outputPath)
mp4, terr := transcodeToMP4(ctx, actual, outputPath, resolutionHeight(job.Resolution))
if terr != nil {
// ffmpeg missing/failed — fall back to the raw render so the job
// still delivers a file (large, but valid).