Split out of #287 (reported by @rakesh0x with the measurements below) so the two asks can move independently.
Current behavior
Every path from a source video file into a canonical episode decodes to JPEG first, then lets the canonical transform re-encode that JPEG into in-band H.264. For an H.265 source that is two lossy steps where one would do.
src/hflow/importers/video.py:171 runs ffmpeg with mjpeg / image2 and writes foxglove.CompressedImage messages with format = "jpeg" (:291). Line 200 states the intent: "JPEG foxglove.CompressedImage messages are source data, not canonical".
hflow.testing.write_video_episode does the same thing for demo and test use.
write_canonical_episode then transcodes those JPEGs to H.264, because in-band H.264 is the canonical target.
Note this moved since #287 was filed: the detour is no longer only in the test helper. import_video_episode is a first-party importer and takes the same route.
Measured (from #287, profile-matched HEVC, 30 s @ 1920x1080 @ 30 fps)
| Step |
Result |
| Source HEVC bytes (same span) |
~7 MB |
| Landing MCAP (JPEG) |
55.3 MB, about 8x source bitrate |
| Canonical episode H.264 media bytes |
24.5 MB, so landing is 2.3x this |
Cold full pipeline (app.test) |
12.0 s, about 2.5x slower than realtime |
of which camera_frame_stats decode |
8.1 s |
At 456x256 the cost is not a problem (2.9 s for 60 s of source). It concentrates at 1080p.
Why it matters
Landing storage is multiplied by about 2.3x before any pipeline run, and every frame passes through two lossy re-encodes, so camera_frame_stats and everything downstream measure artifacts of the JPEG step as well as of the source.
Definition of done
Either a path that transcodes a supported source video to in-band H.264 without the JPEG intermediate, or, if the JPEG landing is deliberate (it isolates the transform from container and codec variety, which is a real benefit), a statement of that in the docs next to import_video_episode so nobody has to measure it to find out.
ffmpeg decodes HEVC directly, so the direct route is available; what it costs the transform's current guarantees is the open question.
Validation
The commands in CONTRIBUTING.md, plus a measurement of landing bytes against canonical bytes on the same source so the 2.3x is shown to move.
Split out of #287 (reported by @rakesh0x with the measurements below) so the two asks can move independently.
Current behavior
Every path from a source video file into a canonical episode decodes to JPEG first, then lets the canonical transform re-encode that JPEG into in-band H.264. For an H.265 source that is two lossy steps where one would do.
src/hflow/importers/video.py:171runs ffmpeg withmjpeg/image2and writesfoxglove.CompressedImagemessages withformat = "jpeg"(:291). Line 200 states the intent: "JPEGfoxglove.CompressedImagemessages are source data, not canonical".hflow.testing.write_video_episodedoes the same thing for demo and test use.write_canonical_episodethen transcodes those JPEGs to H.264, because in-band H.264 is the canonical target.Note this moved since #287 was filed: the detour is no longer only in the test helper.
import_video_episodeis a first-party importer and takes the same route.Measured (from #287, profile-matched HEVC, 30 s @ 1920x1080 @ 30 fps)
app.test)camera_frame_statsdecodeAt 456x256 the cost is not a problem (2.9 s for 60 s of source). It concentrates at 1080p.
Why it matters
Landing storage is multiplied by about 2.3x before any pipeline run, and every frame passes through two lossy re-encodes, so
camera_frame_statsand everything downstream measure artifacts of the JPEG step as well as of the source.Definition of done
Either a path that transcodes a supported source video to in-band H.264 without the JPEG intermediate, or, if the JPEG landing is deliberate (it isolates the transform from container and codec variety, which is a real benefit), a statement of that in the docs next to
import_video_episodeso nobody has to measure it to find out.ffmpegdecodes HEVC directly, so the direct route is available; what it costs the transform's current guarantees is the open question.Validation
The commands in CONTRIBUTING.md, plus a measurement of landing bytes against canonical bytes on the same source so the 2.3x is shown to move.