feat(render B2): render binder writes user edits into AE before render
Build backend images / build content-svc (push) Failing after 52s
Build backend images / build file-svc (push) Failing after 56s
Build backend images / build gateway (push) Failing after 53s
Build backend images / build identity-svc (push) Failing after 1m29s
Build backend images / build notification-svc (push) Failing after 1m38s
Build backend images / build render-svc (push) Failing after 1m53s
Build backend images / build studio-svc (push) Failing after 56s
Build backend images / build content-svc (push) Failing after 52s
Build backend images / build file-svc (push) Failing after 56s
Build backend images / build gateway (push) Failing after 53s
Build backend images / build identity-svc (push) Failing after 1m29s
Build backend images / build notification-svc (push) Failing after 1m38s
Build backend images / build render-svc (push) Failing after 1m53s
Build backend images / build studio-svc (push) Failing after 56s
Edits previously never reached the MP4 (the node rendered template defaults). Now: - render-svc claim includes the saved input values as bindings (GetRenderBindings → saved_scene_contents with non-empty value). - node-agent: new binder.go emits a JSON bind-spec + downloads media locally, runs the pre-existing data-driven bind.jsx via afterfx (sets text layers' Source Text, replaces media footage), saves a bound.aep next to the template, then aerender renders THAT. - 12-min timeout + fresh-AE + done-marker polling (mirrors scan). Non-fatal: on bind failure the job still renders template defaults. Verified binding data flows (edited frl_c1t1/frl_c1t2 → claim bindings). Live MP4 verification needs the updated node-agent.exe re-run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -646,6 +646,31 @@ func (s *Store) GetTemplateCompName(ctx context.Context, originalProjectID uuid.
|
||||
return *comp, nil
|
||||
}
|
||||
|
||||
// GetRenderBindings returns the user's edited input values for a saved project so the
|
||||
// node can write them into the AE project before rendering (the render binder). Only
|
||||
// inputs with a non-empty value are returned (defaults are already in the template).
|
||||
func (s *Store) GetRenderBindings(ctx context.Context, savedProjectID uuid.UUID) ([]models.RenderBinding, error) {
|
||||
rows, err := s.pool.Query(ctx, `
|
||||
SELECT c.key, c.type, COALESCE(c.value, '')
|
||||
FROM studio.saved_scene_contents c
|
||||
JOIN studio.saved_scenes s ON s.id = c.saved_scene_id
|
||||
WHERE s.saved_project_id = $1 AND c.value IS NOT NULL AND c.value <> ''`,
|
||||
savedProjectID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var out []models.RenderBinding
|
||||
for rows.Next() {
|
||||
var b models.RenderBinding
|
||||
if err := rows.Scan(&b.Key, &b.Type, &b.Value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, b)
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
func (s *Store) CreateExportForJob(ctx context.Context, jobID uuid.UUID) (*models.Export, error) {
|
||||
// Look up the job to get tenant/user/project context
|
||||
job, err := s.getJobByIDInternal(ctx, jobID)
|
||||
|
||||
@@ -292,6 +292,10 @@ func (h *InternalHandler) Claim(c *gin.Context) {
|
||||
// Composition to render (-comp). Non-fatal: empty → node uses the render queue.
|
||||
compName, _ := h.store.GetTemplateCompName(c.Request.Context(), job.OriginalProjectID)
|
||||
|
||||
// User's edited input values → the node writes them into the AE project before
|
||||
// rendering (render binder). Non-fatal: empty → renders template defaults.
|
||||
bindings, _ := h.store.GetRenderBindings(c.Request.Context(), job.SavedProjectID)
|
||||
|
||||
c.JSON(http.StatusOK, models.ClaimedJob{
|
||||
JobID: job.ID,
|
||||
SavedProjectID: job.SavedProjectID,
|
||||
@@ -304,6 +308,7 @@ func (h *InternalHandler) Claim(c *gin.Context) {
|
||||
IsBundle: isBundle,
|
||||
BundleMD5: bundleMD5,
|
||||
CompName: compName,
|
||||
Bindings: bindings,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -432,6 +432,17 @@ type ClaimedJob struct {
|
||||
// template's render_aep_comp (e.g. "frfinal"). Empty → node falls back to the
|
||||
// project's render queue.
|
||||
CompName string `json:"comp_name,omitempty"`
|
||||
// Bindings are the user's edited input values to write into the AE project before
|
||||
// rendering (the render binder). Key = AE layer/footage name (frl_c{n}{t|m}{i}).
|
||||
Bindings []RenderBinding `json:"bindings,omitempty"`
|
||||
}
|
||||
|
||||
// RenderBinding is one input value the node writes into the AE project before render:
|
||||
// a Text layer's source text, or a Media footage replacement.
|
||||
type RenderBinding struct {
|
||||
Key string `json:"key"` // AE layer/footage name, e.g. frl_c1t1 / frl_c1m1
|
||||
Type string `json:"type"` // content element type (Text, Media, …)
|
||||
Value string `json:"value"` // text content, or a media URL
|
||||
}
|
||||
|
||||
// OutputUploadURLResponse is returned by POST .../output-upload-url.
|
||||
|
||||
Reference in New Issue
Block a user