Skip to content

feat: play audio and video in the browser, and open the media formats we only named - #649

Merged
andiwand merged 1 commit into
mainfrom
feat/media-html
Aug 1, 2026
Merged

feat: play audio and video in the browser, and open the media formats we only named#649
andiwand merged 1 commit into
mainfrom
feat/media-html

Conversation

@andiwand

@andiwand andiwand commented Aug 1, 2026

Copy link
Copy Markdown
Member

🤖 Generated with Claude Code

Stacked on #648 — it needs internal/html/frontend.cpp for the page's css.

What this is

odrcore already names mp3, mp4, mkv, webp, heic and the rest — it just refused to open them. OpenDocument.droid carried its own translation for exactly that gap: image.html (vendored PhotoSwipe), audio.html and video.html (vendored Plyr, ~213 KB each), with the file copied next to the page under a made-up extension. This brings it here, where the format table already knows what the bytes are.

How

Nothing is decoded, so nothing needs a decoder:

  • open_strategy picks the impl by category rather than by a list of file types someone has to keep in step with. Every image bar the starview metafile becomes internal::ImageFile; audio and video become a new internal::MediaFile. That is what turns on webp, tiff, heif and avif too.
  • html::translate writes an <audio>/<video> with native controls — no player library ships with this.
  • The format table's open/translate_html bits move with it, and the FileType comment that called these "detection only" is no longer true.

No AudioFile/VideoFile wrapper. One would carry nothing the plain DecodedFile does not already have (the bytes, and the type that names them), so create_media_service takes a DecodedFile and translate(const DecodedFile &) dispatches on category. The public surface grows by one enum constant and nothing else.

The media is an HtmlResource, never a data URI. New HtmlResourceType::media, which standard_resource_locator never embeds. bring_offline copies the video next to its page and the http server serves it from the service. base64 would have added a third to the largest thing we emit.

<body class="odr-media"><video src="video.mp4" controls playsinline preload="metadata">Error: video not supported by this browser</video></body>

Notes

  • HtmlResourceType gained a constant, so the three bindings that mirror it by ordinal are updated (jni enum, pybind, ObjC).
  • The http server still buffers a whole response in memory before sending it, so a large video is a large allocation. Pre-existing, and left alone here.
  • Test data has no media files, so media_file_test.cpp builds them from a signature plus a payload in memory — nothing past the signature is ever read.

Test plan

  • odr_test --gtest_filter='media_file.*' — 6 new tests: audio and video pages, the source served and copied as bytes, bring_offline, webp taking the image page.
  • Full suite green: 733 passed, 9 skipped, 0 failed.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0bbd7256d3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/odr/internal/html/media_file.cpp Outdated
Comment thread src/odr/internal/file_type_table.cpp
@andiwand
andiwand force-pushed the feat/inline-frontend-resources branch from d241f89 to 76f1ada Compare August 1, 2026 16:48
Base automatically changed from feat/inline-frontend-resources to main August 1, 2026 22:45
… we only named

odrcore named mp3, mp4, webp and the rest but refused to open them, so
OpenDocument.droid carried its own translation for exactly these: a
PhotoSwipe page for images and two Plyr players for audio and video, each
one a vendored library and the file base64'd or copied next to it. That
belongs here, where the format table already knows what the bytes are.

Nothing is decoded. `open` wraps the bytes for every image bar the
starview metafile, and for all audio and video, and `translate` hands
them to the browser: an `<img>` for the images, an `<audio>` or `<video>`
with native controls for the rest. No player library ships with it.

There is no `AudioFile`/`VideoFile` wrapper to go with them - a wrapper
would carry nothing the plain `DecodedFile` does not already have, so the
service takes that, and `open_strategy` picks the impl by category rather
than by a list of file types it would have to be kept in step with.

The media stays an `HtmlResource` (`HtmlResourceType::media`, never
embedded) instead of a data URI: `bring_offline` copies a video next to
its page and the http server streams it, where base64 would have added a
third to a file that is already the largest thing we emit.
@andiwand
andiwand merged commit b2aa2b1 into main Aug 1, 2026
26 checks passed
@andiwand
andiwand deleted the feat/media-html branch August 1, 2026 22:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant