A plain H.264 MP4 already in the board media folder consistently stalls the headless WebCodecs export. The same file plays fine in the desktop editor preview, serves correctly over HTTP (200 and 206 range requests), and is decodable by ffmpeg.
The file: H.264 High profile, level 4.0, yuv420p, progressive, 1920×1080, 30fps, no audio track, has_b_frames=2.
A second file on the same board that renders perfectly has byte-identical stream properties as reported by ffprobe – same codec, profile, level, pixel format, and also has_b_frames=2 – so ffprobe output alone does not predict which clips will fail.
What I ruled out one variable at a time, each with its own render: the track matte on that layer (removed, still stalls); a large propertyKeyframes.scale track on that layer, 3.15 to 3.55 (removed, still stalls); and POST /api/trim-media, which produces a new file but preserves the same B-frames and still stalls.
What fixed it: a genuine re-encode with B-frames disabled, then POST /api/upload.
ffmpeg -ss S -t D -i in.mp4 -an -c:v libx264 -profile:v main -level 4.0 -pix_fmt yuv420p -bf 0 -g 30 -keyint_min 30 -sc_threshold 0 -r 30 -movflags +faststart out.mp4
That copy renders without any change to the project.
Two smaller points that made this much harder to diagnose:
1. The synchronous POST /render-onserver returns only the generic message "Full server render failed (headless WebCodecs unavailable, timed out, or export error). Use the editor's in-window render instead." The background job endpoint returns the actual cause with a timestamp. It would help a lot if the synchronous endpoint surfaced the same detail.
2. A very short time range (for example rangeStart 8.40, rangeEnd 8.46, i.e. 2 frames) SUCCEEDS on the same project, because it never reaches the "3 consecutive frames failed" threshold. It writes a valid file whose frames are simply blank. So a short range render is not a safe way to check whether a clip decodes.
Steps to reproduce
1. Place an H.264 High/yuv420p clip with B-frames on a video project timeline.
2. POST /render-onserver-job over a range covering that clip, 1.4s or longer.
3. Poll GET /api/video-render-jobs/{id}.
Expected
The clip decodes and renders, as it does in the editor preview.
Actual
Job fails with: Render stalled near 7.67s – 3 consecutive frames failed to render in the headless browser (a clip likely can't be decoded). Try re-encoding that clip or rendering in a different format.
Error output
Error: Render stalled near 7.67s — 3 consecutive frames failed to render in the headless browser (a clip likely can't be decoded). Try re-encoding that clip or rendering in a different format.
at sn (videoExporter.js)
at async Object.exportVideo (VideoEditor.js)
at async Object.renderVideo (VideoProjectRenderPage.js)
Context
Video Editor headless render. Board id New_Pixelgbra_Website. Project 1080×1920, 30fps, 12 channels. Failing clip 1920×1080 H.264 High, level 4.0, yuv420p, has_b_frames=2, no audio.
Environment
App version: 8.8.0
Platform: Windows 11 (AMD64)
Post a Reply