retold-remote 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/README.md +181 -0
- package/docs/_cover.md +14 -0
- package/docs/_sidebar.md +10 -0
- package/docs/_topbar.md +3 -0
- package/docs/audio-viewer.md +133 -0
- package/docs/ebook-reader.md +90 -0
- package/docs/image-viewer.md +90 -0
- package/docs/server-setup.md +262 -0
- package/docs/video-viewer.md +134 -0
- package/html/docs.html +59 -0
- package/package.json +21 -7
- package/source/Pict-Application-RetoldRemote.js +143 -2
- package/source/RetoldRemote-ExtensionMaps.js +33 -0
- package/source/cli/RetoldRemote-Server-Setup.js +82 -67
- package/source/cli/commands/RetoldRemote-Command-Serve.js +5 -26
- package/source/providers/Pict-Provider-CollectionManager.js +934 -0
- package/source/providers/Pict-Provider-FormattingUtilities.js +109 -0
- package/source/providers/Pict-Provider-GalleryFilterSort.js +2 -11
- package/source/providers/Pict-Provider-GalleryNavigation.js +270 -353
- package/source/providers/Pict-Provider-RetoldRemoteIcons.js +52 -0
- package/source/providers/Pict-Provider-ToastNotification.js +96 -0
- package/source/providers/keyboard-handlers/KeyHandler-AudioExplorer.js +88 -0
- package/source/providers/keyboard-handlers/KeyHandler-Gallery.js +190 -0
- package/source/providers/keyboard-handlers/KeyHandler-Sidebar.js +65 -0
- package/source/providers/keyboard-handlers/KeyHandler-VideoExplorer.js +57 -0
- package/source/providers/keyboard-handlers/KeyHandler-Viewer.js +197 -0
- package/source/server/RetoldRemote-ArchiveService.js +2 -12
- package/source/server/RetoldRemote-AudioWaveformService.js +7 -16
- package/source/server/RetoldRemote-CollectionService.js +684 -0
- package/source/server/RetoldRemote-EbookService.js +7 -16
- package/source/server/RetoldRemote-MediaService.js +3 -14
- package/source/server/RetoldRemote-ParimeCache.js +349 -0
- package/source/server/RetoldRemote-ThumbnailCache.js +52 -20
- package/source/server/RetoldRemote-VideoFrameService.js +7 -15
- package/source/views/PictView-Remote-AudioExplorer.js +10 -43
- package/source/views/PictView-Remote-CollectionsPanel.js +1087 -0
- package/source/views/PictView-Remote-Gallery.js +237 -44
- package/source/views/PictView-Remote-ImageViewer.js +1 -34
- package/source/views/PictView-Remote-Layout.js +410 -20
- package/source/views/PictView-Remote-MediaViewer.js +338 -51
- package/source/views/PictView-Remote-SettingsPanel.js +155 -138
- package/source/views/PictView-Remote-TopBar.js +615 -14
- package/source/views/PictView-Remote-VLCSetup.js +766 -0
- package/source/views/PictView-Remote-VideoExplorer.js +20 -54
- package/web-application/css/docuserve.css +73 -0
- package/web-application/docs/README.md +181 -0
- package/web-application/docs/_cover.md +14 -0
- package/web-application/docs/_sidebar.md +10 -0
- package/web-application/docs/_topbar.md +3 -0
- package/web-application/docs/audio-viewer.md +133 -0
- package/web-application/docs/ebook-reader.md +90 -0
- package/web-application/docs/image-viewer.md +90 -0
- package/web-application/docs/server-setup.md +262 -0
- package/web-application/docs/video-viewer.md +134 -0
- package/web-application/docs.html +59 -0
- package/web-application/js/pict-docuserve.min.js +58 -0
- package/web-application/js/pict.min.js +2 -2
- package/web-application/js/pict.min.js.map +1 -1
- package/web-application/retold-remote.js +2558 -439
- package/web-application/retold-remote.js.map +1 -1
- package/web-application/retold-remote.min.js +41 -11
- package/web-application/retold-remote.min.js.map +1 -1
- package/server.js +0 -43
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# eBook Reader
|
|
2
|
+
|
|
3
|
+
The eBook reader displays EPUB files directly in the browser using epub.js, with support for MOBI files through server-side conversion.
|
|
4
|
+
|
|
5
|
+
## Opening an eBook
|
|
6
|
+
|
|
7
|
+
- **From the gallery**: select an `.epub` or `.mobi` file and press `Enter`, or double-click it
|
|
8
|
+
- eBooks are detected by the document type system (pdf, epub, mobi are all in the document category)
|
|
9
|
+
|
|
10
|
+
## EPUB Files
|
|
11
|
+
|
|
12
|
+
EPUB files are loaded and rendered directly in the browser using the epub.js library. No server-side processing is required.
|
|
13
|
+
|
|
14
|
+
### Reading Interface
|
|
15
|
+
|
|
16
|
+
The reader takes up the full viewer area and displays one page at a time in a single-column layout (no spread/two-page mode). Text is styled to match the active theme:
|
|
17
|
+
|
|
18
|
+
- Body text uses the theme's primary text color
|
|
19
|
+
- Background matches the theme's primary background
|
|
20
|
+
- Links use the theme's accent color
|
|
21
|
+
- Font: Georgia, Times New Roman, serif
|
|
22
|
+
- Line height: 1.6
|
|
23
|
+
- Padding: 20px horizontal, 40px vertical
|
|
24
|
+
|
|
25
|
+
### Table of Contents
|
|
26
|
+
|
|
27
|
+
A sidebar on the left shows the book's table of contents. Each chapter is a clickable button. Subchapters are indented up to two levels.
|
|
28
|
+
|
|
29
|
+
| Action | Effect |
|
|
30
|
+
|--------|--------|
|
|
31
|
+
| Click a chapter | Jump to that chapter |
|
|
32
|
+
| Click "TOC" button | Toggle the sidebar open/closed |
|
|
33
|
+
|
|
34
|
+
The TOC sidebar starts collapsed and can be toggled with the TOC button in the controls bar.
|
|
35
|
+
|
|
36
|
+
### Page Navigation
|
|
37
|
+
|
|
38
|
+
Controls at the bottom of the reader:
|
|
39
|
+
|
|
40
|
+
| Button | Action |
|
|
41
|
+
|--------|--------|
|
|
42
|
+
| **TOC** | Toggle table of contents sidebar |
|
|
43
|
+
| **Prev** | Go to previous page |
|
|
44
|
+
| **Next** | Go to next page |
|
|
45
|
+
|
|
46
|
+
Page navigation moves through the reflowed content. Pages are determined by the viewport size, not by the original book pagination.
|
|
47
|
+
|
|
48
|
+
## MOBI Files
|
|
49
|
+
|
|
50
|
+
MOBI files (and AZW format) require server-side conversion to EPUB before they can be displayed. This requires **ebook-convert** from Calibre to be installed on the server.
|
|
51
|
+
|
|
52
|
+
### Conversion Flow
|
|
53
|
+
|
|
54
|
+
1. The client requests conversion via `/api/media/ebook-convert?path=<file>`
|
|
55
|
+
2. The server runs `ebook-convert` to produce an EPUB file
|
|
56
|
+
3. The converted EPUB is cached on disk
|
|
57
|
+
4. The client fetches the EPUB from `/api/media/ebook/<cacheKey>/<filename>`
|
|
58
|
+
5. The EPUB is rendered using the same epub.js reader
|
|
59
|
+
|
|
60
|
+
If ebook-convert is not available, MOBI files show a message explaining that conversion is needed and linking to the Calibre download page.
|
|
61
|
+
|
|
62
|
+
### Installing Calibre (for MOBI support)
|
|
63
|
+
|
|
64
|
+
**macOS:**
|
|
65
|
+
```bash
|
|
66
|
+
brew install calibre
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Ubuntu/Debian:**
|
|
70
|
+
```bash
|
|
71
|
+
sudo apt-get install calibre
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Docker:**
|
|
75
|
+
The provided Dockerfile includes Calibre. If using the minimal Dockerfile, add:
|
|
76
|
+
```dockerfile
|
|
77
|
+
RUN apt-get update && apt-get install -y calibre && rm -rf /var/lib/apt/lists/*
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## PDF Files
|
|
81
|
+
|
|
82
|
+
PDF files are rendered using the browser's native PDF viewer in an iframe. No additional tools or libraries are required. The browser provides its own controls for page navigation, zoom, and search.
|
|
83
|
+
|
|
84
|
+
## Limitations
|
|
85
|
+
|
|
86
|
+
- MOBI conversion requires Calibre's `ebook-convert` on the server
|
|
87
|
+
- DRM-protected ebooks cannot be read
|
|
88
|
+
- Complex EPUB layouts (fixed-layout EPUBs, heavy CSS) may not render perfectly
|
|
89
|
+
- The reader uses single-page mode only (no two-page spreads)
|
|
90
|
+
- Page numbers shown in the UI correspond to the reflowed content, not the original book pagination
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Image Viewer
|
|
2
|
+
|
|
3
|
+
The image viewer displays image files with three fit modes, manual zoom, and EXIF orientation support.
|
|
4
|
+
|
|
5
|
+
## Opening an Image
|
|
6
|
+
|
|
7
|
+
- **From the gallery**: select a file and press `Enter`, or double-click a tile
|
|
8
|
+
- **Force any file as image**: press `1` in the gallery or viewer to open it in the image viewer regardless of extension
|
|
9
|
+
|
|
10
|
+
## Fit Modes
|
|
11
|
+
|
|
12
|
+
Cycle through fit modes by pressing `z`.
|
|
13
|
+
|
|
14
|
+
### Fit to Window
|
|
15
|
+
|
|
16
|
+
Scales the image to fill the viewport while preserving aspect ratio (CSS `object-fit: contain` behavior). The image is never larger than the viewport.
|
|
17
|
+
|
|
18
|
+
### Original if Smaller (default)
|
|
19
|
+
|
|
20
|
+
Displays the image at its native resolution if it fits within the viewport. If the image is larger than the viewport, it scales down using the same logic as Fit to Window. This avoids upscaling small images.
|
|
21
|
+
|
|
22
|
+
### Original Size
|
|
23
|
+
|
|
24
|
+
Always displays at native resolution regardless of viewport size. Large images will overflow and can be scrolled.
|
|
25
|
+
|
|
26
|
+
When the fit mode changes, a brief overlay indicator appears for 1.2 seconds showing the active mode name.
|
|
27
|
+
|
|
28
|
+
## Zoom
|
|
29
|
+
|
|
30
|
+
| Key | Action | Range |
|
|
31
|
+
|-----|--------|-------|
|
|
32
|
+
| `+` or `=` | Zoom in | Up to 8x |
|
|
33
|
+
| `-` | Zoom out | Down to 0.25x |
|
|
34
|
+
| `0` | Reset zoom to 1x | |
|
|
35
|
+
| Click on image | Toggle between 1x and 2x | |
|
|
36
|
+
|
|
37
|
+
Each zoom step multiplies or divides by 1.25. The zoom level applies on top of the current fit mode calculation.
|
|
38
|
+
|
|
39
|
+
When zoomed beyond the viewport, the cursor changes to a zoom-out icon and the image can be scrolled. When the image fits, the cursor shows zoom-in.
|
|
40
|
+
|
|
41
|
+
## Mouse Interactions
|
|
42
|
+
|
|
43
|
+
- **Click** on the image toggles between 1x and 2x zoom
|
|
44
|
+
- **Scroll** when zoomed to pan the image
|
|
45
|
+
|
|
46
|
+
## Keyboard Shortcuts
|
|
47
|
+
|
|
48
|
+
These work while viewing any image:
|
|
49
|
+
|
|
50
|
+
| Key | Action |
|
|
51
|
+
|-----|--------|
|
|
52
|
+
| `z` | Cycle fit mode (Fit to Window -> Original if Smaller -> Original Size) |
|
|
53
|
+
| `+` / `=` | Zoom in |
|
|
54
|
+
| `-` | Zoom out |
|
|
55
|
+
| `0` | Reset zoom |
|
|
56
|
+
| `f` | Toggle fullscreen |
|
|
57
|
+
| `i` | Toggle file info overlay |
|
|
58
|
+
| Right / `j` | Next file |
|
|
59
|
+
| Left / `k` | Previous file |
|
|
60
|
+
| `v` | Stream with VLC |
|
|
61
|
+
| `d` | Distraction-free mode |
|
|
62
|
+
| `Esc` | Back to gallery |
|
|
63
|
+
|
|
64
|
+
## File Info Overlay
|
|
65
|
+
|
|
66
|
+
Press `i` to show metadata about the current image:
|
|
67
|
+
|
|
68
|
+
- **Size**: file size in KB/MB
|
|
69
|
+
- **Dimensions**: width x height in pixels
|
|
70
|
+
- **Format**: image format
|
|
71
|
+
- **Modified**: last modification date
|
|
72
|
+
- **Path**: file path on the server
|
|
73
|
+
|
|
74
|
+
The overlay appears in the top-right corner and can be toggled on and off.
|
|
75
|
+
|
|
76
|
+
## Supported Formats
|
|
77
|
+
|
|
78
|
+
png, jpg, jpeg, gif, webp, svg, bmp, ico, avif, tiff, tif, heic, heif
|
|
79
|
+
|
|
80
|
+
Animated GIFs and WebP animations play in the browser natively. SVG files render as vector graphics. HEIC/HEIF support depends on the browser.
|
|
81
|
+
|
|
82
|
+
## EXIF Orientation
|
|
83
|
+
|
|
84
|
+
Images are displayed with `image-orientation: from-image`, meaning EXIF rotation data is respected automatically. Portrait photos taken on phones display upright without manual rotation.
|
|
85
|
+
|
|
86
|
+
## Thumbnails
|
|
87
|
+
|
|
88
|
+
In the gallery, image thumbnails are generated server-side using sharp (preferred) or ImageMagick (fallback) at 200x200 pixels in webp format. Thumbnails are cached on disk and invalidated when the source file changes.
|
|
89
|
+
|
|
90
|
+
If no image processing tool is available, the full image is loaded directly.
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# Server Setup and Docker
|
|
2
|
+
|
|
3
|
+
## Installation
|
|
4
|
+
|
|
5
|
+
### From npm
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g retold-remote
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### From source
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
git clone <repo-url>
|
|
15
|
+
cd retold-remote
|
|
16
|
+
npm install
|
|
17
|
+
npm run build
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The build step bundles the client-side JavaScript with Quackage and copies assets into `web-application/`.
|
|
21
|
+
|
|
22
|
+
## Running the Server
|
|
23
|
+
|
|
24
|
+
### CLI Command
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
retold-remote serve [content-path] [options]
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Or using the short alias:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
rr serve /path/to/media
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
If `content-path` is omitted, the current directory is served.
|
|
37
|
+
|
|
38
|
+
### Options
|
|
39
|
+
|
|
40
|
+
| Flag | Description | Default |
|
|
41
|
+
|------|-------------|---------|
|
|
42
|
+
| `-p, --port [port]` | Port to listen on | Random 7000-7999 |
|
|
43
|
+
| `-H, --hashed-filenames` | Enable hashed filename mode (hides real paths from browser) | Off |
|
|
44
|
+
| `-c, --cache-path [path]` | Root cache directory | `./dist/retold-cache/` |
|
|
45
|
+
| `--cache-thumbnails [path]` | Override thumbnail cache location | `<cache-root>/thumbnails/` |
|
|
46
|
+
| `--cache-archives [path]` | Override archive extraction cache | `<cache-root>/archives/` |
|
|
47
|
+
| `--cache-video-frames [path]` | Override video frame cache | `<cache-root>/video-frames/` |
|
|
48
|
+
| `--cache-audio-waveforms [path]` | Override audio waveform cache | `<cache-root>/audio-waveforms/` |
|
|
49
|
+
|
|
50
|
+
### Direct Node.js
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
node server.js [content-path]
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Default port is `8086` when using `server.js` directly.
|
|
57
|
+
|
|
58
|
+
### Environment Variables
|
|
59
|
+
|
|
60
|
+
| Variable | Description | Default |
|
|
61
|
+
|----------|-------------|---------|
|
|
62
|
+
| `PORT` | HTTP port | `8086` (server.js) or random (CLI) |
|
|
63
|
+
| `RETOLD_HASHED_FILENAMES` | Set to `true` to enable hashed filenames | `false` |
|
|
64
|
+
|
|
65
|
+
### Examples
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# Serve current directory on port 8086
|
|
69
|
+
node server.js
|
|
70
|
+
|
|
71
|
+
# Serve a specific folder
|
|
72
|
+
node server.js /mnt/nas/media
|
|
73
|
+
|
|
74
|
+
# CLI with custom port
|
|
75
|
+
retold-remote serve /mnt/nas/media -p 3000
|
|
76
|
+
|
|
77
|
+
# Hashed filenames for privacy
|
|
78
|
+
retold-remote serve /mnt/nas/media -H
|
|
79
|
+
|
|
80
|
+
# Custom cache location (useful for Docker volumes)
|
|
81
|
+
retold-remote serve /media -c /cache
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Configuration
|
|
85
|
+
|
|
86
|
+
### Settings Persistence
|
|
87
|
+
|
|
88
|
+
User preferences are stored in the browser via `localStorage` under the key `retold-remote-settings`. These include:
|
|
89
|
+
|
|
90
|
+
- Theme selection
|
|
91
|
+
- View mode (grid or list)
|
|
92
|
+
- Thumbnail size (small, medium, large)
|
|
93
|
+
- Gallery filter and sort preferences
|
|
94
|
+
- Show hidden files toggle
|
|
95
|
+
- Autoplay video / audio toggles
|
|
96
|
+
- Image fit mode
|
|
97
|
+
- Sidebar state
|
|
98
|
+
- Filter presets
|
|
99
|
+
|
|
100
|
+
Settings are loaded on page load and saved whenever a preference changes.
|
|
101
|
+
|
|
102
|
+
### Server Capabilities
|
|
103
|
+
|
|
104
|
+
On startup the server probes for optional tools and reports availability at `GET /api/media/capabilities`. The Settings panel in the UI shows which tools are detected.
|
|
105
|
+
|
|
106
|
+
| Tool | Detection Method | Feature |
|
|
107
|
+
|------|-----------------|---------|
|
|
108
|
+
| **sharp** | `require('sharp')` | Image thumbnail generation |
|
|
109
|
+
| **ImageMagick** | `identify --version` | Fallback image thumbnails |
|
|
110
|
+
| **ffmpeg** | `ffmpeg -version` | Video thumbnails, frame extraction, audio waveforms |
|
|
111
|
+
| **ffprobe** | `ffprobe -version` | Media metadata (duration, dimensions, codec, bitrate) |
|
|
112
|
+
| **VLC** | macOS: `/Applications/VLC.app`; Linux: `vlc --version` | External video playback |
|
|
113
|
+
| **7-Zip** | `7z --help` | Archive browsing (rar, 7z, tar.*) |
|
|
114
|
+
| **ebook-convert** | `ebook-convert --version` (Calibre) | MOBI/AZW to EPUB conversion |
|
|
115
|
+
|
|
116
|
+
Without any optional tools the application still works: images are served directly (no thumbnails), videos play in the browser, and zip/cbz archives use native extraction via yauzl.
|
|
117
|
+
|
|
118
|
+
### Thumbnail Cache
|
|
119
|
+
|
|
120
|
+
Thumbnails are cached on disk using a SHA-256 hash of `<filepath>:<mtime>:<width>x<height>`. When the source file is modified the mtime changes, invalidating the cache entry automatically.
|
|
121
|
+
|
|
122
|
+
Default location: `./dist/retold-cache/thumbnails/`
|
|
123
|
+
|
|
124
|
+
Default thumbnail size: 200x200, format: webp.
|
|
125
|
+
|
|
126
|
+
Thumbnails are served with `Cache-Control: public, max-age=86400`.
|
|
127
|
+
|
|
128
|
+
### Hashed Filenames Mode
|
|
129
|
+
|
|
130
|
+
When enabled (`-H` flag or `RETOLD_HASHED_FILENAMES=true`), real file paths are never exposed to the browser. Instead, deterministic 10-character hex hashes derived from SHA-256 are used in URLs and API responses. The same path always produces the same hash across server restarts.
|
|
131
|
+
|
|
132
|
+
## Docker
|
|
133
|
+
|
|
134
|
+
### Using the Included Dockerfile
|
|
135
|
+
|
|
136
|
+
A `Dockerfile` is provided in the repository root:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
docker build -t retold-remote .
|
|
140
|
+
docker run -p 8086:8086 -v /path/to/media:/media retold-remote
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Inline Dockerfile
|
|
144
|
+
|
|
145
|
+
If you need to create a Dockerfile from scratch, here is a complete working version:
|
|
146
|
+
|
|
147
|
+
```dockerfile
|
|
148
|
+
FROM node:20-slim
|
|
149
|
+
|
|
150
|
+
# Install optional tools for full functionality
|
|
151
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
152
|
+
ffmpeg \
|
|
153
|
+
imagemagick \
|
|
154
|
+
p7zip-full \
|
|
155
|
+
calibre \
|
|
156
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
157
|
+
|
|
158
|
+
WORKDIR /app
|
|
159
|
+
|
|
160
|
+
# Copy package files and install dependencies
|
|
161
|
+
COPY package.json package-lock.json ./
|
|
162
|
+
RUN npm ci --omit=dev && npm cache clean --force
|
|
163
|
+
|
|
164
|
+
# Install sharp (optional image processing)
|
|
165
|
+
RUN npm install sharp || true
|
|
166
|
+
|
|
167
|
+
# Copy application source and built assets
|
|
168
|
+
COPY source/ source/
|
|
169
|
+
COPY web-application/ web-application/
|
|
170
|
+
COPY css/ css/
|
|
171
|
+
COPY html/ html/
|
|
172
|
+
COPY server.js ./
|
|
173
|
+
|
|
174
|
+
# Create cache directory
|
|
175
|
+
RUN mkdir -p /cache
|
|
176
|
+
|
|
177
|
+
# Default port
|
|
178
|
+
ENV PORT=8086
|
|
179
|
+
|
|
180
|
+
EXPOSE 8086
|
|
181
|
+
|
|
182
|
+
# Serve /media with cache at /cache
|
|
183
|
+
CMD ["node", "server.js", "/media"]
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Docker Compose
|
|
187
|
+
|
|
188
|
+
```yaml
|
|
189
|
+
version: "3.8"
|
|
190
|
+
services:
|
|
191
|
+
retold-remote:
|
|
192
|
+
build: .
|
|
193
|
+
ports:
|
|
194
|
+
- "8086:8086"
|
|
195
|
+
volumes:
|
|
196
|
+
- /path/to/media:/media:ro
|
|
197
|
+
- retold-cache:/cache
|
|
198
|
+
environment:
|
|
199
|
+
- PORT=8086
|
|
200
|
+
restart: unless-stopped
|
|
201
|
+
|
|
202
|
+
volumes:
|
|
203
|
+
retold-cache:
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Docker Usage Notes
|
|
207
|
+
|
|
208
|
+
- Mount your media folder to `/media` (read-only is fine with `:ro`)
|
|
209
|
+
- Mount a volume to `/cache` for persistent thumbnail and frame caches
|
|
210
|
+
- The `node:20-slim` base keeps the image small while the `apt-get` packages add full media processing
|
|
211
|
+
- `calibre` is the largest optional package; omit it if you do not need MOBI/AZW ebook conversion
|
|
212
|
+
- `sharp` is installed separately because it has native bindings that may fail on some architectures; the `|| true` ensures the build continues without it
|
|
213
|
+
|
|
214
|
+
### Minimal Dockerfile (No Optional Tools)
|
|
215
|
+
|
|
216
|
+
If you only need basic browsing without thumbnails or media probing:
|
|
217
|
+
|
|
218
|
+
```dockerfile
|
|
219
|
+
FROM node:20-slim
|
|
220
|
+
|
|
221
|
+
WORKDIR /app
|
|
222
|
+
|
|
223
|
+
COPY package.json package-lock.json ./
|
|
224
|
+
RUN npm ci --omit=dev && npm cache clean --force
|
|
225
|
+
|
|
226
|
+
COPY source/ source/
|
|
227
|
+
COPY web-application/ web-application/
|
|
228
|
+
COPY css/ css/
|
|
229
|
+
COPY html/ html/
|
|
230
|
+
COPY server.js ./
|
|
231
|
+
|
|
232
|
+
ENV PORT=8086
|
|
233
|
+
EXPOSE 8086
|
|
234
|
+
|
|
235
|
+
CMD ["node", "server.js", "/media"]
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
This produces an image under 200MB. Images display directly (no thumbnails), videos play in the browser, and zip/cbz archives use native extraction.
|
|
239
|
+
|
|
240
|
+
## Archive Browsing
|
|
241
|
+
|
|
242
|
+
Archives appear as navigable folders in the file browser. Clicking an archive opens it and displays its contents as if they were a regular directory.
|
|
243
|
+
|
|
244
|
+
**Supported formats:**
|
|
245
|
+
|
|
246
|
+
| Format | Tool Required |
|
|
247
|
+
|--------|---------------|
|
|
248
|
+
| `.zip`, `.cbz` | None (native yauzl) |
|
|
249
|
+
| `.7z`, `.rar`, `.tar`, `.tar.gz`, `.tar.bz2`, `.tar.xz`, `.tgz`, `.cbr` | 7-Zip |
|
|
250
|
+
|
|
251
|
+
Files inside archives can be viewed, thumbnailed, and probed just like regular files. Archive contents are extracted to the cache directory on demand.
|
|
252
|
+
|
|
253
|
+
## VLC Streaming
|
|
254
|
+
|
|
255
|
+
The VLC integration allows streaming media files to a VLC player running on the server machine. Press `v` in the media viewer to send the current file to VLC.
|
|
256
|
+
|
|
257
|
+
Setup instructions for macOS, Windows, and Linux are available in the Settings panel under "VLC Protocol Setup". The setup creates a `vlc://` protocol handler that opens files in VLC when triggered from the browser.
|
|
258
|
+
|
|
259
|
+
**Platform details:**
|
|
260
|
+
- **macOS**: Creates an AppleScript app at `/Applications/VLCProtocol.app` and registers it as a URL handler
|
|
261
|
+
- **Windows**: Registry entry or batch script that maps `vlc://` to the VLC executable
|
|
262
|
+
- **Linux**: Desktop file at `~/.local/share/applications/vlc-protocol.desktop` registered with xdg-mime
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Video Viewer and Explorer
|
|
2
|
+
|
|
3
|
+
The video viewer provides an action menu for choosing how to interact with a video, inline browser playback, VLC streaming, and a frame explorer for scrubbing through video content visually.
|
|
4
|
+
|
|
5
|
+
## Opening a Video
|
|
6
|
+
|
|
7
|
+
- **From the gallery**: select a video file and press `Enter`, or double-click it
|
|
8
|
+
- **Force any file as video**: press `2` in the gallery or viewer to open it in the video viewer regardless of extension
|
|
9
|
+
|
|
10
|
+
## Video Action Menu
|
|
11
|
+
|
|
12
|
+
When a video is opened, an action menu appears instead of playing immediately. The menu shows the filename and a preview frame extracted from the video midpoint.
|
|
13
|
+
|
|
14
|
+
### Menu Options
|
|
15
|
+
|
|
16
|
+
| Key | Option | Description |
|
|
17
|
+
|-----|--------|-------------|
|
|
18
|
+
| `Space` / `Enter` | **Play in Browser** | Plays the video inline with HTML5 `<video>` controls |
|
|
19
|
+
| `e` | **Explore Video Frames** | Opens the frame explorer (requires ffmpeg) |
|
|
20
|
+
| `t` | **Extract Thumbnail** | Extracts a single frame from the midpoint |
|
|
21
|
+
| `v` | **Stream with VLC** | Sends the file to VLC on the server machine |
|
|
22
|
+
|
|
23
|
+
The preview frame in the menu is loaded automatically from the server. If ffmpeg is not available, the Explore and Thumbnail options are hidden.
|
|
24
|
+
|
|
25
|
+
Navigation shortcuts still work while the menu is open:
|
|
26
|
+
|
|
27
|
+
| Key | Action |
|
|
28
|
+
|-----|--------|
|
|
29
|
+
| Right / `j` | Skip to next file |
|
|
30
|
+
| Left / `k` | Skip to previous file |
|
|
31
|
+
| `Esc` | Back to gallery |
|
|
32
|
+
|
|
33
|
+
## In-Browser Playback
|
|
34
|
+
|
|
35
|
+
Pressing `Space` or `Enter` replaces the action menu with an HTML5 video player. The player has native browser controls for play/pause, seeking, volume, and fullscreen.
|
|
36
|
+
|
|
37
|
+
Below the player, a **stats bar** shows:
|
|
38
|
+
|
|
39
|
+
- **Duration** (formatted as mm:ss)
|
|
40
|
+
- **Resolution** (width x height)
|
|
41
|
+
- **Codec** (e.g., h264, hevc, vp9)
|
|
42
|
+
- **Bitrate** (in kbps or Mbps)
|
|
43
|
+
- **File Size** (formatted)
|
|
44
|
+
|
|
45
|
+
The stats bar also includes buttons to jump to the Video Explorer or stream with VLC.
|
|
46
|
+
|
|
47
|
+
### Autoplay
|
|
48
|
+
|
|
49
|
+
Autoplay is off by default. Enable it in Settings > Gallery > Autoplay video. When enabled, videos begin playing as soon as the player loads.
|
|
50
|
+
|
|
51
|
+
## Video Explorer
|
|
52
|
+
|
|
53
|
+
The video explorer extracts multiple frames from a video and displays them in a grid, letting you scrub through content visually without playing the video.
|
|
54
|
+
|
|
55
|
+
### Opening the Explorer
|
|
56
|
+
|
|
57
|
+
- From the video action menu, press `e`
|
|
58
|
+
- From the video stats bar during playback, click "Explore Video"
|
|
59
|
+
|
|
60
|
+
### Frame Grid
|
|
61
|
+
|
|
62
|
+
Frames are displayed in a responsive grid. Each frame card shows:
|
|
63
|
+
|
|
64
|
+
- The extracted frame image
|
|
65
|
+
- A timestamp label (e.g., "1:23")
|
|
66
|
+
- A frame index number
|
|
67
|
+
|
|
68
|
+
Double-click any frame to open it in a full-screen preview overlay.
|
|
69
|
+
|
|
70
|
+
### Controls
|
|
71
|
+
|
|
72
|
+
At the top of the explorer:
|
|
73
|
+
|
|
74
|
+
| Control | Description |
|
|
75
|
+
|---------|-------------|
|
|
76
|
+
| Frame count dropdown | Choose 10, 20, 40, 60, or 100 frames (default: 20) |
|
|
77
|
+
| Full-res checkbox | Extract frames at 1920x1080 instead of 640x360 |
|
|
78
|
+
| Refresh button | Re-extract frames with current settings |
|
|
79
|
+
|
|
80
|
+
### Info Bar
|
|
81
|
+
|
|
82
|
+
Below the controls, an info bar displays video metadata:
|
|
83
|
+
|
|
84
|
+
- Duration
|
|
85
|
+
- Resolution
|
|
86
|
+
- Codec
|
|
87
|
+
- File size
|
|
88
|
+
- Number of extracted frames
|
|
89
|
+
|
|
90
|
+
### Timeline Bar
|
|
91
|
+
|
|
92
|
+
Below the frame grid, a timeline bar shows the video duration with markers at each extracted frame's position. The timeline also shows markers for any custom frames you extract.
|
|
93
|
+
|
|
94
|
+
**Click anywhere on the timeline** to extract a frame at that exact timestamp. The extracted frame appears in the grid in chronological order, styled with a dashed border to distinguish it from the evenly-spaced frames.
|
|
95
|
+
|
|
96
|
+
### Frame Preview
|
|
97
|
+
|
|
98
|
+
Double-click any frame in the grid to open a full-screen preview overlay showing the frame at full size.
|
|
99
|
+
|
|
100
|
+
In the preview:
|
|
101
|
+
|
|
102
|
+
| Key | Action |
|
|
103
|
+
|-----|--------|
|
|
104
|
+
| Left / `k` | Previous frame |
|
|
105
|
+
| Right / `j` | Next frame |
|
|
106
|
+
| `Esc` | Close preview |
|
|
107
|
+
|
|
108
|
+
The Back button in the preview header also closes it. Navigation moves through all frames (regular and custom) in chronological order.
|
|
109
|
+
|
|
110
|
+
### Keyboard Shortcuts
|
|
111
|
+
|
|
112
|
+
| Key | Action |
|
|
113
|
+
|-----|--------|
|
|
114
|
+
| `Esc` | Back to video viewer |
|
|
115
|
+
|
|
116
|
+
## VLC Streaming
|
|
117
|
+
|
|
118
|
+
Press `v` from the action menu, stats bar, or viewer to send the current video to VLC running on the server. This is useful for files in formats the browser cannot play natively.
|
|
119
|
+
|
|
120
|
+
VLC protocol setup instructions are available in Settings > VLC Protocol Setup, with platform-specific guides for macOS, Windows, and Linux.
|
|
121
|
+
|
|
122
|
+
## File Info Overlay
|
|
123
|
+
|
|
124
|
+
Press `i` while viewing a video to see metadata:
|
|
125
|
+
|
|
126
|
+
- Size, Duration, Resolution, Codec, Bitrate, Format, Modified date, Path
|
|
127
|
+
|
|
128
|
+
## Supported Formats
|
|
129
|
+
|
|
130
|
+
**Natively recognized extensions**: mp4, webm, mov, mkv, avi, wmv, flv, m4v, ogv, mpg, mpeg, mpe, mpv, m2v, ts, mts, m2ts, vob, 3gp, 3g2, f4v, rm, rmvb, divx, asf, mxf, dv, nsv, nuv, y4m, wtv, swf, dat
|
|
131
|
+
|
|
132
|
+
**Browser playback support** varies by format. Most browsers play mp4 (h264), webm (vp8/vp9), and ogg natively. For other formats, use VLC streaming or the frame explorer.
|
|
133
|
+
|
|
134
|
+
**Force any file as video** by pressing `2` in the gallery or viewer to bypass extension detection. This is useful for misnamed files (e.g., `.avii` instead of `.avi`).
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
7
|
+
<meta name="description" content="Retold Remote Documentation">
|
|
8
|
+
|
|
9
|
+
<title>Retold Remote - Documentation</title>
|
|
10
|
+
|
|
11
|
+
<!-- Docuserve base stylesheet -->
|
|
12
|
+
<link href="css/docuserve.css" rel="stylesheet">
|
|
13
|
+
<!-- PICT Dynamic View CSS Container -->
|
|
14
|
+
<style id="PICT-CSS"></style>
|
|
15
|
+
|
|
16
|
+
<!-- Load the PICT library -->
|
|
17
|
+
<script src="js/pict.min.js" type="text/javascript"></script>
|
|
18
|
+
<!-- Bootstrap the Application -->
|
|
19
|
+
<script type="text/javascript">
|
|
20
|
+
Pict.safeOnDocumentReady(function()
|
|
21
|
+
{
|
|
22
|
+
// Intercept AppData.Docuserve creation to inject DocsBaseURL
|
|
23
|
+
// before pict-docuserve starts fetching markdown files.
|
|
24
|
+
var _origInit = PictDocuserve.prototype.onAfterInitializeAsync;
|
|
25
|
+
PictDocuserve.prototype.onAfterInitializeAsync = function(fCallback)
|
|
26
|
+
{
|
|
27
|
+
var _appData = this.pict.AppData;
|
|
28
|
+
// One-shot setter: when onAfterInitializeAsync assigns
|
|
29
|
+
// AppData.Docuserve, modify DocsBaseURL before loadCatalog runs.
|
|
30
|
+
Object.defineProperty(_appData, 'Docuserve',
|
|
31
|
+
{
|
|
32
|
+
configurable: true,
|
|
33
|
+
enumerable: true,
|
|
34
|
+
set: function(pValue)
|
|
35
|
+
{
|
|
36
|
+
pValue.DocsBaseURL = 'docs/';
|
|
37
|
+
Object.defineProperty(_appData, 'Docuserve',
|
|
38
|
+
{
|
|
39
|
+
configurable: true,
|
|
40
|
+
enumerable: true,
|
|
41
|
+
writable: true,
|
|
42
|
+
value: pValue
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
return _origInit.call(this, fCallback);
|
|
47
|
+
};
|
|
48
|
+
Pict.safeLoadPictApplication(PictDocuserve, 2);
|
|
49
|
+
});
|
|
50
|
+
</script>
|
|
51
|
+
</head>
|
|
52
|
+
<body>
|
|
53
|
+
<!-- The root container for the Pict application -->
|
|
54
|
+
<div id="Docuserve-Application-Container"></div>
|
|
55
|
+
|
|
56
|
+
<!-- Load the Docuserve PICT Application Bundle -->
|
|
57
|
+
<script src="js/pict-docuserve.min.js" type="text/javascript"></script>
|
|
58
|
+
</body>
|
|
59
|
+
</html>
|