Clip transcoding: ffmpeg in the backend image, panel recipe in the node docs

This commit is contained in:
Melvin Strobl
2026-10-14 07:30:36 +02:00
parent 659799d1e5
commit 1964c5b2e8
2 changed files with 49 additions and 0 deletions
+43
View File
@@ -110,6 +110,49 @@ ring and streams bytes to connected screens. New frames eventually replace
old ones. A volatile artifact returned as a run result is copied to persistent
storage; emitted frames alone are not recorded as run artifacts.
### Making clips playable on an LVGL panel
A wall panel that renders dashboards natively, such as an ESP32-P4 running
openpanel, decodes only H.264 Constrained Baseline (in software, about 29 fps
at 640×360) and MJPEG. It refuses clips straight from a phone or camera, which
are usually Main or High profile at 1080p or more. Re-encode those with a node
that takes a `video` input port `clip` and has a `video` output port
`panel_clip`:
```python
import os
import subprocess
import tempfile
import fluksio
# H.264 Constrained Baseline, at most 640x360 and 15 fps, mono AAC.
PANEL = [
"-c:v", "libx264", "-profile:v", "baseline", "-level:v", "3.1",
"-pix_fmt", "yuv420p", "-fpsmax", "15",
"-vf", "scale=w=640:h=360:force_original_aspect_ratio=decrease:force_divisible_by=2",
"-preset", "veryfast", "-crf", "23", "-g", "30",
"-c:a", "aac", "-ac", "1", "-b:a", "64k", "-movflags", "+faststart",
]
def process(clip):
source = fluksio.load_artifact(clip)
with tempfile.TemporaryDirectory() as tmp:
target = os.path.join(tmp, "panel.mp4")
subprocess.run(
["ffmpeg", "-nostdin", "-loglevel", "error", "-i", source, *PANEL, target],
check=True,
timeout=600,
)
name = os.path.splitext(clip.get("name") or "clip")[0] + "-panel.mp4"
return {"panel_clip": fluksio.save_artifact(target, name, "video/mp4")}
```
Use it only for clips headed for such a panel. Browsers play the originals,
and the result plays there too, just smaller. The Docker image ships `ffmpeg`;
a [remote worker](workers.md) needs it on its `PATH`.
## Printing
`print` and `fluksio.logger.info(...)` are captured in the node logs. The