Document player features and usage
This commit is contained in:
@@ -1,17 +1,70 @@
|
||||
# C41 Recorder Player
|
||||
|
||||
Run:
|
||||
A small local web player for the C41 recorder archive. It turns the recorder's
|
||||
dated video folders into a simple daily view that is easy to search and play.
|
||||
|
||||
## Features
|
||||
|
||||
- Shows recordings on a full 24-hour timeline.
|
||||
- Uses the time in each filename to place clips at the correct time of day.
|
||||
- Shows recorded minutes in light blue and empty periods in dark blue.
|
||||
- Lets you choose the recording date.
|
||||
- Plays browser-friendly MP4 files immediately.
|
||||
- Converts an AVI clip automatically when no MP4 copy exists.
|
||||
- Provides a YouTube-style play/pause button and progress bar.
|
||||
- Provides volume control and mute.
|
||||
- Jumps backward or forward by 10 seconds.
|
||||
- Crosses clip boundaries and skips empty periods during 10-second jumps.
|
||||
- Zooms the timeline to inspect a smaller time range.
|
||||
- Supports keyboard shortcuts.
|
||||
- Can manually encode the archive from the Encoding menu.
|
||||
- Shows encoding progress, completed files, skipped files, and errors.
|
||||
- Never overwrites an existing transcoded file.
|
||||
- Keeps all original AVI recordings unchanged.
|
||||
|
||||
## Start The Player
|
||||
|
||||
From this directory, run:
|
||||
|
||||
```sh
|
||||
python3 server.py
|
||||
```
|
||||
|
||||
Then open <http://127.0.0.1:8765>. The server indexes the dated folders in
|
||||
`/home/human/Videos/Yassine Salon/C41/media` and uses FFmpeg to convert only the
|
||||
currently playing AVI clip for the browser. Original recordings are unchanged.
|
||||
Open <http://127.0.0.1:8765> in a browser.
|
||||
|
||||
To use another archive or port:
|
||||
The default source archive is:
|
||||
|
||||
`/home/human/Videos/Yassine Salon/C41/media`
|
||||
|
||||
The default browser-friendly output archive is:
|
||||
|
||||
`/home/human/Videos/Yassine Salon/C41/media-mp4`
|
||||
|
||||
## Keyboard Shortcuts
|
||||
|
||||
- `Space`: play or pause.
|
||||
- `Left arrow`: go back 10 seconds.
|
||||
- `Right arrow`: go forward 10 seconds.
|
||||
- `M`: mute or unmute.
|
||||
|
||||
## Encoding
|
||||
|
||||
Open **Encoding** in the player and press **Start**. The encoder creates small,
|
||||
browser-compatible H.264/AAC MP4 files in `media-mp4`, preserving the dated
|
||||
folder structure.
|
||||
|
||||
Encoding can take time because the original files use HEVC video. You can keep
|
||||
using the player while encoding runs. Files that already have an MP4 copy are
|
||||
reported as skipped. A temporary file is used during each conversion, so an
|
||||
interrupted conversion cannot damage an existing file.
|
||||
|
||||
## Custom Folders And Ports
|
||||
|
||||
To use a different output folder or port:
|
||||
|
||||
```sh
|
||||
python3 server.py "/path/to/media" --port 9000
|
||||
python3 server.py "/path/to/output-media" --source "/path/to/source-media" --port 9000
|
||||
```
|
||||
|
||||
The source and output folders should contain dated folders named like
|
||||
`20260827`, with clips named like `09.28.36.avi` or `09.28.36.mp4`.
|
||||
|
||||
+20
@@ -14,6 +14,11 @@
|
||||
.header { display: flex; align-items: center; justify-content: space-between; padding: 8px 0 16px; }
|
||||
.header h1 { font-size: 18px; font-weight: 500; }
|
||||
.header select { background: var(--surface); color: var(--text); border: none; padding: 6px 10px; border-radius: 3px; font-size: 14px; cursor: pointer; }
|
||||
.help { margin-bottom: 14px; background: var(--surface); border-radius: 8px; overflow: hidden; }
|
||||
.help summary { padding: 11px 16px; color: var(--text); cursor: pointer; font-size: 13px; }
|
||||
.help-content { padding: 0 16px 14px; color: var(--dim); font-size: 13px; line-height: 1.55; }
|
||||
.help-content p { margin-top: 8px; }
|
||||
.help-content strong { color: var(--text); font-weight: 500; }
|
||||
|
||||
/* player wrapper */
|
||||
.player-wrap { position: relative; background: #000; border-radius: 12px; overflow: hidden; }
|
||||
@@ -89,6 +94,19 @@
|
||||
<select id="date"></select>
|
||||
</div>
|
||||
|
||||
<details class="help">
|
||||
<summary>How to use this player</summary>
|
||||
<div class="help-content">
|
||||
<p><strong>Choose a date:</strong> Select a recording day at the top right.</p>
|
||||
<p><strong>Find a recording:</strong> Light blue sections contain video. Dark sections are times when nothing was recorded. Click a light blue section to play it.</p>
|
||||
<p><strong>Move through video:</strong> Use the red bar below the video to move within the current clip. Use the back and forward buttons, or the left and right arrow keys, to jump 10 seconds. Jumps automatically cross clips and skip gaps.</p>
|
||||
<p><strong>Audio:</strong> Use the speaker button to mute. Hover over it to adjust volume. Press <strong>M</strong> to mute or unmute.</p>
|
||||
<p><strong>Play and pause:</strong> Press the play button, click the video, or press <strong>Space</strong>.</p>
|
||||
<p><strong>Timeline zoom:</strong> Press <strong>+</strong> or <strong>-</strong> to see a smaller part of the day in more detail.</p>
|
||||
<p><strong>Encoding:</strong> Open the Encoding menu and press Start to create browser-friendly copies. Existing copies are skipped and never overwritten.</p>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<div class="player-wrap paused" id="player-wrap">
|
||||
<video id="video" playsinline></video>
|
||||
<div class="big-play"><svg viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/></svg></div>
|
||||
@@ -373,6 +391,8 @@
|
||||
if (e.target.tagName === "SELECT" || e.target.tagName === "INPUT") return;
|
||||
if (e.code === "ArrowLeft") { e.preventDefault(); seekBy(-10); }
|
||||
else if (e.code === "ArrowRight") { e.preventDefault(); seekBy(10); }
|
||||
else if (e.code === "Equal" || e.code === "NumpadAdd") { e.preventDefault(); zoom = Math.min(24, zoom * 2); drawTimeline(); }
|
||||
else if (e.code === "Minus" || e.code === "NumpadSubtract") { e.preventDefault(); zoom = Math.max(1, zoom / 2); drawTimeline(); }
|
||||
else if (e.code === "Space") { e.preventDefault(); if (activeClip) video.paused ? video.play() : video.pause(); }
|
||||
else if (e.code === "KeyM") { video.muted = !video.muted; updateVolIcon(); }
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user