# Listening Dashboard

Turn a JSON queue and local audio or video files into a responsive, offline HTML review page. Each item shows a native media player, review notes, a transcript, and a status. A summary and status groups make a batch easy to scan.

Use it for podcast edits, training recordings, accessibility narration, voice-over takes, interview clips, or a personal media review queue. It is a human listening aid. It does not analyze sound, transcribe speech, change review decisions, or contact an AI service.

## Requirements and installation

- Python **3.11 or newer**, including its standard library.
- A current browser with support for your chosen media format.
- No Python packages, account, API key, internet connection, or paid subscription is required to run the tool. This tool has no third-party Python dependencies or hosted services.

Download or clone MyTools, then open a terminal in `01-listening-dashboard`. No installation command is needed. Check Python:

**Windows PowerShell**

```powershell
py -3 --version
```

**macOS / Linux**

```sh
python3 --version
```

If Python is missing or older than 3.11, install an appropriate Python 3 release for your operating system, then reopen the terminal. Windows examples use `py -3`; use `python` instead if that is the command provided by your installation. macOS and Linux examples use `python3`.

## Run the included example

The example includes a script that creates a two-second synthetic tone. It is deliberately labeled as a tone, not a spoken recording. Start playback with your device volume low.

**Windows PowerShell**

```powershell
py -3 examples/create_demo_tone.py
py -3 tool.py --queue examples/queue.json --media-root output --output output/listening.html
Start-Process output/listening.html
```

**macOS / Linux**

```sh
python3 examples/create_demo_tone.py
python3 tool.py --queue examples/queue.json --media-root output --output output/listening.html
```

Open `output/listening.html` in your browser. On macOS you can run `open output/listening.html`; on desktop Linux, `xdg-open output/listening.html` usually opens it. You can also double-click the HTML file. Generated example files stay under `output/`; the committed queue and tone generator remain unchanged.

The page works directly from disk. It has no JavaScript, external fonts, tracking code, CDN, or server. Rerunning either generation command requires `--force` if its output already exists.

## Use your own recordings

1. Put your recordings in a folder, for example `work/media/`.
2. Create `work/queue.json` using the schema below.
3. Run the dashboard generator.
4. Open the result, listen, and record your conclusions in the queue's `notes` and `status` fields.
5. Rebuild with `--force` and reload the browser after edits.

```sh
python3 tool.py --queue work/queue.json --output work/review.html
python3 tool.py --queue work/queue.json --output work/review.html --force
```

On Windows, replace `python3` with `py -3`.

If the media is stored separately, choose its root explicitly:

```sh
python3 tool.py --queue work/queue.json --media-root recordings --output work/review.html
```

In this case, a queue value of `"audio": "interviews/take-01.mp3"` resolves to `recordings/interviews/take-01.mp3`. Without `--media-root`, all media paths resolve relative to the queue file's directory. The tool validates every attached file before writing the dashboard.

## Queue schema

```json
{
  "title": "Recording review",
  "description": "Check clarity, pacing, and the final sentence.",
  "entries": [
    {
      "item_id": "take-001",
      "title": "Introduction, first take",
      "status": "ready",
      "notes": "Listen for background noise near the beginning.",
      "transcript": "Welcome. Today we will explore a practical example.",
      "audio": "media/introduction.wav",
      "video": "media/introduction.mp4",
      "duration_seconds": 18.5
    }
  ]
}
```

| Field | Required | Meaning |
| --- | --- | --- |
| `entries` | Yes | Array of review items; an empty array is valid. |
| `title`, `description` | No | Dashboard heading and introductory text. |
| `item_id` | Yes | Unique, nonempty item identifier. |
| `title` on an item | Yes | Nonempty display title. |
| `status` | Yes | One of the six status values below. |
| `notes` | No | Plain text review notes. |
| `transcript` | No | Plain text, with line breaks preserved; supplied by you. |
| `audio`, `video` | No | Relative local media paths, using `/` between directories. |
| `duration_seconds` | No | A finite nonnegative number, supplied by you; the tool does not measure duration. |

Statuses, in display order: `ready`, `in_review`, `needs_changes`, `approved`, `on_hold`, `archived`. Status is your own recorded decision; `approved` does not mean that the tool performed a quality assessment.

Unknown fields are rejected to catch mistakes. Omit an optional field when unused; do not set it to `null`. Titles, notes, and transcripts are treated as plain text and escaped before inclusion in HTML.

Allowed audio extensions: `.wav`, `.mp3`, `.m4a`, `.ogg`, `.opus`, `.flac`, `.aac`. Allowed video extensions: `.mp4`, `.webm`, `.ogv`, `.mov`, `.m4v`. An allowed extension does not guarantee browser codec support. For example, an MP4 file may contain a codec your browser cannot decode.

## Command reference

```text
tool.py --queue FILE --output FILE.html [--media-root DIRECTORY] [--force]
```

| Option | Behavior |
| --- | --- |
| `--queue` | Required UTF-8 JSON input. UTF-8 with a byte-order mark is accepted. |
| `--output` | Required HTML destination; parent directories are created. |
| `--media-root` | Optional directory that attached media must stay inside. Defaults to the queue's directory. |
| `--force` | Replace the output HTML if it already exists. It never permits overwriting the queue or its media. |
| `--help` | Show command help. |

Success returns exit code `0`; input or output errors return `2`. Existing output is preserved when validation fails.

## Portability, privacy, and limitations

- All processing is local. Media is linked, not uploaded, copied, or embedded.
- The HTML uses relative, URL-encoded media links. Move the page together with its media while keeping their relative folder layout. Moving only the HTML will break playback. On Windows, output and media must be on the same drive.
- Media paths cannot be absolute, use Windows backslashes, or escape the configured media root, including through symbolic links. Remote media URLs are not accepted. This is input validation, not a sandbox against someone who can concurrently replace files on your computer.
- The HTML contains the supplied titles, notes, and full transcripts. Anyone with access to that HTML can read them. Share only content you intend others to see.
- The page does not save edits or playback progress. Update the JSON and rebuild it. Status groups appear when they contain items.
- Browser playback depends on local-file permissions and codec support. The **Open audio file** or **Open video file** link can be used with a suitable media player if inline playback fails.
- This dashboard does not perform AI verification. It complements a separate audio-review tool by providing a convenient place for a person to listen.

## Checks

Run the standard-library tests from this directory:

```powershell
py -3 -m unittest discover -s tests -v
```

```sh
python3 -m unittest discover -s tests -v
```

Tests cover HTML escaping, portable media links, directory traversal and symlink escapes, validation, custom media roots, and overwrite protection, including hardlinks to input files. Link tests skip only when the operating system does not permit creating the relevant link. Test media files are inert fixtures; tests do not claim to verify browser playback.
