Files
amethyst/desktopApp/plans/2026-10-11-desktop-video-compression-manual-testing.md
davotoula 680d1ea1ce feat(uploads): tell the user when a video encode was discarded for not being smaller
Android already warns when the compressed file is larger than the
original; desktop kept it silently. The compressor now attaches an
UploadNotice when it falls back to the remuxed original, worded as a
warning dialog like the other upload notices.
2026-10-11 20:44:54 +01:00

144 lines
9.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Manual Testing Sheet — Desktop Video Compression (phase 1)
**Spec:** `desktopApp/plans/2026-10-11-desktop-video-compression.md`
**Plan:** `desktopApp/plans/2026-10-11-desktop-video-compression-plan.md`
**Branch:** `feat/desktop-video-compression`
**Run:** `./gradlew :desktopApp:run` — and, for the no-ffmpeg sections, `AMETHYST_FFMPEG_DISABLED=1 ./gradlew :desktopApp:run`
(the `run` task's JVM inherits the shell environment; a bare `PATH` is **not** enough, the locator finds Homebrew by design).
Everything below is 🟢 LIVE: built, unit-tested where the logic allows, and ready to click through.
The automated suite already covers the rules table, the slider mapping, the ffmpeg command lines,
encoder selection, the stall watchdog and a set of real encodes (`./gradlew :commons:jvmTest --tests "*Ffmpeg*"`).
This sheet covers what only a person with the app, a server and a few clips can check.
**Legend for results:** ✅ pass · ❌ fail (write what happened) · ⏭️ skipped/blocked
---
## Setup (do once)
- [ ] `ffmpeg -version` and `ffprobe -version` work in a terminal (Homebrew: `brew install ffmpeg`).
- [ ] `ffmpeg -hide_banner -encoders | grep -E "libx264|hevc_videotoolbox|libx265"` — note which HEVC encoders this machine has.
- [ ] Clips in `~/Downloads`:
- **`big.mp4`**, a high-bitrate 1080p source: a real phone or camera clip of 10–30 s (phones write 1080p at 10–20 Mbps), or build one:
`ffmpeg -f lavfi -i "color=c=gray:s=1920x1080:r=30,noise=alls=100:allf=t+u" -f lavfi -i sine -t 10 -shortest -pix_fmt yuv420p -c:v libx264 -crf 18 -preset ultrafast -metadata title=secret -metadata location=+48.2082+016.3738/ ~/Downloads/big.mp4`
(check: `ffprobe` reports a video `bit_rate` well above 4 000 000). Note its `shasum -a 256`.
- `file_example_MOV_1920_2_2MB.mov` (the investigation's clip; sha256 `ead8b50c…e40c62`). It is 1080p H.264 at only ~450 kbps, so every encode above Low comes out **larger** than the source and the pipeline uploads the remuxed original — it proves the size rule (row 2.7), not the encoder.
- a **portrait phone video** (taller than wide, shot on a phone)
- an **HDR iPhone clip** (Settings › Camera › Record Video › HDR on; the probe sees `color_transfer` `arib-std-b67`)
- an animated **GIF**
- a **corrupt video**: `head -c 300000 file_example_MOV_1920_2_2MB.mov > broken.mov`
- a **long clip** (≥ 2 min) for the NIP-95 refusal
- [ ] A Blossom server you can upload to (blossom.band works) and, for §7, a NIP-95 relay-event upload target.
- [ ] A terminal open for `pgrep -l ffmpeg`, `shasum -a 256`, `curl` and `ffprobe`.
> `ffprobe` one-liner used throughout:
> `ffprobe -v error -select_streams V:0 -show_entries stream=width,height,codec_name,bit_rate:format_tags -of json <file>`
---
## 1. Composer with ffmpeg installed 🟢 LIVE
Open the post composer, attach media with the **Upload Media** button.
| # | Step | Expected | Result |
|---|------|----------|--------|
| 1.1 | Hover the attach button | Tooltip reads **Upload Media** | |
| 1.2 | Pick `file_example_MOV_1920_2_2MB.mov` | The quality slider shows **4 stops** (Low / Medium / High / Uncompressed), the **H.265** switch is visible, the **strip metadata** toggle is hidden while the slider is below Uncompressed | |
| 1.3 | Read the label at High | `High · 1080p video → 1080p, 4 Mbps` (the file's real standard, not an example) | |
| 1.4 | Move to Medium, then Low | `Medium · 1080p video → 720p, 2 Mbps`, then `Low · 1080p video → 480p, 0.75 Mbps` | |
| 1.5 | Move to Uncompressed | No video phrase; the H.265 switch disappears; the strip-metadata toggle **appears** | |
| 1.6 | Add a **photo** to the same post, then move the slider through every stop | Still 4 stops; the label shows both parts, e.g. `High · images up to 1920 px · 1080p video → 1080p, 4 Mbps` | |
| 1.7 | New post: photo first, slider to **Very High**, then add a video | The slider snaps to **High** (Very High has no video rule) and keeps 4 stops | |
| 1.8 | Remove the video again | 5 stops return; the position stays on High (known and accepted: Very High is not restored) | |
| 1.9 | Pick the **GIF** | A **Convert GIF to MP4** switch appears; turning it on hides the slider | |
| 1.10 | Profile › edit › picture picker | Tooltip still reads **Upload Image** | |
---
## 2. Upload results — the hash check 🟢 LIVE
Upload **`big.mp4`** to **blossom.band** from the composer, once per row, and fetch the blob
(`curl -o out.mp4 <url>`; `shasum -a 256 out.mp4`; the `ffprobe` one-liner).
| # | Step | Expected | Result |
|---|------|----------|--------|
| 2.1 | **High**, H.265 off | sha256 **differs** from the source; the blob is much **smaller**; `.mp4`; 1920×1080; `codec_name` `h264`; video `bit_rate` ≤ 4 400 000; no `title`/`location` in `format_tags`; the progress bar shows **Compressing** before **Uploading** | |
| 2.2 | **Low** | short side **480** (854×480); bitrate well under 2.1's | |
| 2.3 | **High**, H.265 **on**, machine with an HEVC encoder | `codec_name` `hevc`; plays in QuickTime/Safari (the `hvc1` tag) | |
| 2.4 | **High**, H.265 **on**, machine **without** an HEVC encoder | A toast **"H.265 not available … encoded as H.264"**; the blob is `h264` | |
| 2.5 | **Uncompressed**, strip metadata **on** | sha256 differs from the source (remuxed); `codec_name` is the **source's**; bitrate is the source's; no `title`/`location` tags | |
| 2.6 | **Uncompressed**, strip metadata **off** | sha256 **equals** the source | |
| 2.7 | `file_example_MOV_1920_2_2MB.mov` at **High** | The upload is the **remuxed original**: sha256 differs from `ead8b50c…e40c62`, `codec_name` `h264`, bitrate ≈ 450 kbps (the source's, not 4 Mbps), size ≈ 2.2 MB, tags gone. A dialog **"Original video kept — Compressing did not make the video smaller…"** | |
| 2.8 | `file_example_MOV_1920_2_2MB.mov` at **Low** | Compressed to 854×480 (the only level whose encode is smaller than this source) | |
---
## 3. Special sources 🟢 LIVE
| # | Step | Expected | Result |
|---|------|----------|--------|
| 3.1 | Portrait phone video at High | Label names its real standard (short side = width); uploaded blob is **portrait** (e.g. 1080×1920), plays upright, no rotation metadata | |
| 3.2 | HDR iPhone clip at High | A toast **"HDR video — Compressed HDR video looks flat…"**; the upload still completes | |
| 3.3 | GIF with **Convert GIF to MP4** on | The post carries an `.mp4` at the GIF's own size; it loops/plays in the feed | |
| 3.4 | Corrupt `broken.mov` at High | A toast **"Video compression failed — The original file is being uploaded instead…"**; the upload completes with the original bytes | |
| 3.5 | A clip with no audio track | Encodes and uploads without error | |
---
## 4. Concurrency, cancellation, cleanup 🟢 LIVE
| # | Step | Expected | Result |
|---|------|----------|--------|
| 4.1 | Three videos in one post, post it, run `pgrep -l ffmpeg` repeatedly | **One** `ffmpeg` at a time; all three upload | |
| 4.2 | Start a long encode and **quit the app** mid-way | `pgrep -l ffmpeg` is empty within a second; `ls ~/.amethyst/tmp/amethyst_video_*` (or wherever `AmethystTempDir.rootDir()` points) shows nothing | |
| 4.3 | Start an encode and **cancel** the post | No `ffmpeg` left; no `amethyst_video_*` temp left | |
| 4.4 | After a successful upload | No `amethyst_video_*` temp left | |
---
## 5. NIP-95 (file inside the event) 🟢 LIVE
| # | Step | Expected | Result |
|---|------|----------|--------|
| 5.1 | Pick the **long clip** with a NIP-95 target at High | Refused **at once** with the "too big for NIP-95" error — no multi-minute encode first (`pgrep ffmpeg` stays empty) | |
| 5.2 | A clip that compresses to under 80 KB (a 1–2 s clip at Low) | Encodes, then publishes as an event | |
---
## 6. Chat file dialog 🟢 LIVE
Open a DM, attach a video through the chat file dialog.
| # | Step | Expected | Result |
|---|------|----------|--------|
| 6.1 | With ffmpeg | The slider shows 4 stops with the video label; **no** H.265 switch (the chat state has none); the strip-metadata toggle is **always** shown | |
| 6.2 | Send `big.mp4` at High | The received video is 1080p H.264 (same checks as 2.1) | |
| 6.3 | Encrypted DM attachment | Same result; the plaintext was compressed before encryption | |
---
## 7. Without ffmpeg 🟢 LIVE
Quit the app and relaunch with `AMETHYST_FFMPEG_DISABLED=1 ./gradlew :desktopApp:run`.
| # | Step | Expected | Result |
|---|------|----------|--------|
| 7.1 | Pick a video in the composer | **No** slider for the video alone, **no** H.265 switch, one grey hint line **"Install ffmpeg to compress videos. Until then videos are uploaded as they are."**, the strip-metadata toggle **stays visible** | |
| 7.2 | Photo + video | The slider shows **5 stops** (images only) and its label has **no** video phrase | |
| 7.3 | GIF | No Convert GIF to MP4 switch | |
| 7.4 | Upload `big.mp4` | sha256 **equals** the source (nothing touched it) | |
| 7.5 | Chat file dialog with a video | Same hint; the slider appears only when a photo is also attached | |
| 7.6 | Video thumbnails in the feed | Still render (the thumbnail cache now shares the locator; disabled means no ffmpeg thumbnails, posters from the event still show) | |
---
## 8. Packaged app from Finder 🟢 LIVE
`./gradlew :desktopApp:packageDmg`, install from `desktopApp/build/compose/binaries/main/dmg/`, launch **from Finder** (not from a terminal — Finder-launched apps have an empty launchd `PATH`).
| # | Step | Expected | Result |
|---|------|----------|--------|
| 8.1 | Pick a video in the composer with Homebrew ffmpeg installed | The video controls appear (found through `/opt/homebrew/bin`) | |
| 8.2 | Upload `big.mp4` at High | Same result as 2.1 | |