openvibers/openvibe.mediahub CHANGELOG.md
CHANGELOG.md
| 1 | # Changelog |
| 2 | |
| 3 | What changed in OpenVibe.MediaHub, newest first. Each site also publishes its patch notes at /updates. |
| 4 | |
| 5 | ## Unreleased |
| 6 | |
| 7 | - A recording's picture-in-picture plays in sync with it (2026-11-13, Maticus: "the robot PiP freezes on VODs"). The |
| 8 | streams a Live recording drew over itself now each plays its own VOD over the watch page: while the main video is |
| 9 | inside a span the PiP is at `offset + (main - from)`, outside it the PiP hides. It follows the main's play, pause, |
| 10 | seeks and speed (a seek on one seeks the other, a wait on either pauses both), drift over 0.3 s is nudged with a |
| 11 | playbackRate factor between 0.95 and 1.05, and over 2 s seeks. The box is openvibe-shared's OVFloat (drag, tuck, |
| 12 | pinch/grip size, its place kept per device); a tap (or Enter) swaps it with the main view, sources and times both |
| 13 | ways. Several spans work, and a span whose PiP VOD is gone hides with one quiet line. The server keeps those |
| 14 | missing spans in `vod.pips` (`missing: true`) and gives each its `vod_id`. Tests: `test/vod-pip-core.test.js` (the |
| 15 | time mapping and the drift decision), `test/vod-pip-chrome.test.js` (two local videos: seeks on the main move the |
| 16 | PiP, pause/rate/drift follow, a tap swaps) and `test/video-pips.test.js` (the page hands the player each span). |
| 17 | |
| 18 | - openvibe.pics' home icons and "Choose a picture" (2026-11-13, the owner's phone). The "What you get", "The links a |
| 19 | picture gets" and "What we promise, in writing" cards gave the shared showcase bare glyph names, which it drew as |
| 20 | Font Awesome placeholders with no font and no mapping: every icon was an empty 40 px square. They are now the glyph |
| 21 | registry's SVG, drawn on the server. The upload button lost its pink to the shared presence sheet's later `.ovp-btn` |
| 22 | rule, leaving near-black text on the dark card; Pics' buttons are scoped to `.ovp-page`, 44 px tall, and the label |
| 23 | carries the upload glyph. Tests: `test/pics.test.js` checks every feature icon is inline SVG, and |
| 24 | `test/pics-browser.test.js` opens the home at 390 and 1280 px in dark and light and fails on an unpainted icon, a |
| 25 | zero-size glyph, or button text that is invisible against what is behind it. |
| 26 | - YouTube-shaped watch addresses (2026-11-07, the owner: "on openvibe.video we should copy the style of YouTube… /watch, |
| 27 | and then like the actual video ID"). Every recording, clip and upload now has a short, stable, unguessable watch id — |
| 28 | 11 characters of URL-safe base64, minted once by OpenVibe.Media (one id space across VODs and clips) — and its page is |
| 29 | `/watch?v=<id>` (with `&t=<seconds>` for a moment). The old `/v/:id`, `/c/:id` and `/u/:id` answer 301 to it, carrying |
| 30 | the query over. An upload's id is copied from its Media VOD into `video_uploads.watch_id` (migration |
| 31 | `0024_watch_ids.sql`: a nullable column and a partial unique index; rows written before it are backfilled in a batch at |
| 32 | boot). Canonical links, JSON-LD, the share sheet, the sitemap, llms.txt, IndexNow, the Markdown twins, the menu card |
| 33 | and every card built from data name the watch page. Tests: `test/video-watch-ids.test.js` (backfill once and distinct, |
| 34 | old → 301 → new with `t` kept, canonical/share/sitemap/twin at `/watch?v=`). |
| 35 | |
| 36 | - The drive has a bin, and the API has the drive's full controls (2026-11-07). Deleting a file — from its page, its |
| 37 | card, or `DELETE /api/v1/files/:id` — puts it in the bin for 30 days instead of deleting it: its share links stop at |
| 38 | once, its bytes stay in OpenVibe.Media, and it still counts against storage. `/files/bin` in the sidebar (with a |
| 39 | count) lists what is there, each file with Restore and Delete forever, and an Empty the bin button; a file binned more |
| 40 | than 30 days ago is purged hourly in batches of 200 (the row is soft-deleted and Media is asked for the object). The |
| 41 | API now also takes `PATCH /api/v1/files/:id` (`name`, `folder_id`; null is the top), `PATCH /api/v1/folders/:id` |
| 42 | (`name`), `DELETE /api/v1/folders/:id` (409 `folder.not_empty`), `GET /api/v1/files?q=` across every folder, |
| 43 | `POST /api/v1/files/:id/restore` and `DELETE /api/v1/files/:id?forever=1`; a sync key may rename and move but may not |
| 44 | delete a folder. Migration `0023_files_bin.sql`. |
| 45 | - openvibe.download looks and works like a drive (2026-11-07, the owner: "a competitor to Google Drive … sleek and easy |
| 46 | to use and intuitive and minimalist while being powerful … full controls"). `/files` is a sidebar (New, My files, |
| 47 | Shared links, Backups, the storage meter) beside the files: folder tiles, then file cards with the picture or a |
| 48 | coloured tile for the kind (PDF, document, spreadsheet, slides, archive, code, audio, video), or the same cards as |
| 49 | rows in the list view. Search covers every folder (`?q=`, and it filters what is on screen as you type); sort by |
| 50 | newest, oldest, name or size, remembered. Files dropped anywhere on the page upload into the folder on screen, many |
| 51 | at once, with a tray that shows each one's progress and refreshes the list when they are in. Every file and folder |
| 52 | has a menu: Download, Share a link, Move to…, Rename, Delete; a folder deletes only when it is empty. On a phone, New |
| 53 | is a floating button that opens a bottom sheet, and a menu opens as a sheet over the tab bar. |
| 54 | A file's page shows the file large beside what you can do with it: who can open a link (three choices, drawn as |
| 55 | cards), expiry as chips, Move, Rename, the facts and Delete. Fixed on the way: a folder made inside a folder went to |
| 56 | the top level. Everything still works with JavaScript off. |
| 57 | - Content labels show on openvibe.video and OpenVibe.Pics (2026-11-02, L1). Cards, watch pages and pictures say in |
| 58 | words what they carry (Nudity, Strong language, 18+…), and each viewer's own choice on openvibe.network shows, |
| 59 | blurs or hides them. A maker always sees their own; on a video's or picture's own page a hide covers it with a |
| 60 | "Show" button rather than leaving the page empty. Owners set the labels in the edit forms: AI suggestions are |
| 61 | marked and never ticked for them, and ticking nothing clears them. openvibe-shared 4.94.0. |
| 62 | - OpenVibe.Pics says in writing what it does with a picture (2026-10-30, the market research): three policy pages — |
| 63 | `/exif` (the metadata — the GPS position, the camera, the time it was taken — is taken out by us, and the file you |
| 64 | upload is not kept), `/content-policy` (what is not allowed, how a rule is enforced, and what this site does not |
| 65 | do) and `/ai-training` (we do not train on the pictures you upload; the one thing that asks a model is the alt text |
| 66 | you ask for, and it keeps a hash, not the picture). Every number on them comes from the service's own |
| 67 | configuration, and where the code cannot promise something the page says so: the stripping happens after your file |
| 68 | arrives, and a promise about AI is not a lock. The home says in one line who removes the metadata, and a picture's |
| 69 | page shows its links side by side — the file itself, Markdown, BBCode and HTML — copyable without an account. |
| 70 | |
| 71 | - The watch pages say what the video is (2026-10-30, the market research): under the title, the kind — a stream |
| 72 | recording, a clip or an upload — with the day it was streamed (Live's own stream time), its length and its views. |
| 73 | Every word comes from the item's own fields; a fact Live does not give is left out, not guessed. A clip credits the |
| 74 | recording it was cut from and links back to it, at the moment the clip starts; a recording that is not public any |
| 75 | more is named as such. The share box writes the page's own link out (a plain link, and `?t=125` to open the video at |
| 76 | 2:05 — a moment, not a clip: nothing is stored). Every export says what it is for (TXT to read, SRT for editors, VTT |
| 77 | for web players, JSON for programs, CSV for spreadsheets) and the transcript says it was written by AI, and can be |
| 78 | wrong. The menus on a phone open above the app bar, so their buttons are not behind it. |
| 79 | |
| 80 | - openvibe.video's sitemap carries an image entry per video (SEO-17): the same entry that names `<video:video>` also names its thumbnail as `<image:image><image:loc>` — built from the thumbnail the video entry already has, so it is only there when the URL exists and is https. Entries without a thumbnail keep no image, the video entries and the ten-minute cache are unchanged, and openvibe.download's private shares and openvibe.pics (`/i/` is in its robots' disallow) are untouched. `test/video-pages.test.js` pins one image per video entry, the same URL as its `thumbnail_loc`. |
| 81 | - openvibe.video's search basics (2026-10-20). A watch page nobody wrote about gets a description of its own (who, |
| 82 | how long, when, its first words) instead of the site tagline. A recording under two minutes with nothing written |
| 83 | about it is noindex and out of the sitemap: 118 of 785 were under a minute, mostly test streams. The sitemap lists |
| 84 | every recording and clip (it stopped at 150 of each) with a video entry each (openvibe-shared 4.5.0) and is kept |
| 85 | ten minutes. Structured data and the sitemap name Media's file with `?raw=1`, since Media answers crawlers a page |
| 86 | otherwise. |
| 87 | - MediaHub reaches OpenVibe.Media with its Network service token (audience `openvibe.media`, grants |
| 88 | `media.object.upload` and `media.object.read` on namespace `media-hub`). `MEDIAHUB_MEDIA_APP_KEY` is gone |
| 89 | (compatibility register C-71). |
| 90 | - OpenVibe.Video step A: openvibe.video now serves public, read-only watch pages for OpenVibe.Live's stream |
| 91 | recordings and clips (`/v/:id`, `/c/:id`, `/@:username`, WebVTT captions and chapters), reading Live's public |
| 92 | JSON API server-side, signed out. No uploads and no new storage. |
| 93 | - OpenVibe.Video step B: the VOD watch page now shows a chat replay of the stream (read from OpenVibe.Chat, |
| 94 | oldest first, the first 1,000 messages) and read-only comments with the OpenVibe.Community thread link, plus the |
| 95 | `MEDIAHUB_CHAT_URL` setting. |
| 96 | - OpenVibe.Video step C: playlists. Signed-in people can save recordings and clips into playlists (100 playlists per |
| 97 | person, 500 items each), share them by link (public/unlisted), and watch them back with the `?list=` up-next flow. |
| 98 | Sign-in now works on the video host with its own callback URI, and the playlists are part of account export and |
| 99 | deletion. |
| 100 | - openvibe.pics is still parked: its vhost answers 302 to https://openvibe.network/ and proxies nothing. The app |
| 101 | no longer has "coming" pages or host-based brand handling. |
| 102 | |
| 103 | ## 0.1.0 — 2026-10-08 |
| 104 | |
| 105 | - openvibe.download v1, a private drive. Account-only uploads go into OpenVibe.Media: a plain form, or resumable |
| 106 | parts. Files and folders are private, with per-person limits. |
| 107 | - Share links that expire, need a signed-in downloader and can name accounts (matched by subject; unknown names refused). |
| 108 | - Reports, suspension and a staff queue. |
| 109 | - Sandboxed attachment downloads. |
| 110 | - openvibe.pics and openvibe.video answer with honest "coming" pages. |
| 111 | - Account export and deletion (ADR-033) with openvibe-sdk/account-data. |
| 112 | - Pins: openvibe-contracts v0.118.0, openvibe-sdk v0.36.0, openvibe-shared v2.15.0. |
| 113 |