music: officer-music sidecar + /api/music streaming proxy
Adds an officer-music sidecar that owns an audio-streaming HTTP server, and a
thin authenticating proxy on the platform. All processing (path resolution,
byte-range streaming, ffprobe duration) is in the sidecar; the platform only
authenticates and forwards.
App-facing contract (handoff):
GET /api/music/stream?path=<home-relative path>&token=<jwt>
- auth via userMiddleware (Bearer or ?token= for media elements)
- 200 full / 206 on Range, with Accept-Ranges, Content-Length,
Content-Range, Content-Type, and X-Audio-Duration (seconds, ffprobe)
- path resolved within HOME_DIR, traversal-guarded (400); 404 if missing
Purpose: stream + seek without pre-downloading the whole file — the app can
read X-Audio-Duration instead of scanning for VBR duration.
Pieces:
- sidecar/music/{index.ts,stream-audio.ts}: Bun.serve on a random port, /stream
+ /health, duration cached by path+mtime; reports its port via a new
music:server sidecar event on connect.
- api/music/{sidecar-server.ts,router.ts}: capture the port; reverse-proxy
/api/music/* → sidecar, streaming status + headers through.
- protocol.ts music:server event; hono.ts mounts /api/music; ecosystem adds
officer-music.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,8 @@ import { settingsRouter } from './api/settings/settings';
|
||||
import { dashboardsRouter } from './api/dashboards';
|
||||
import { taskLogsRouter } from './api/task-logs/task-logs';
|
||||
import { router as fileBrowserRouter } from './api/file-browser/router';
|
||||
import { musicRouter } from './api/music/router';
|
||||
import './api/music/sidecar-server'; // side-effect: capture the officer-music audio server port
|
||||
import { devServerRouter, devServerProxyRouter } from './api/dev-server/router';
|
||||
import { dockRouter } from './api/dock/dock';
|
||||
import { integrationsRouter, googleCallbackHandler } from './api/integrations/integrations';
|
||||
@@ -86,6 +88,7 @@ protectedRouter.route('/user', settingsRouter);
|
||||
protectedRouter.route('/dashboards', dashboardsRouter);
|
||||
protectedRouter.route('/task-logs', taskLogsRouter);
|
||||
protectedRouter.route('/file-browser', fileBrowserRouter);
|
||||
protectedRouter.route('/music', musicRouter);
|
||||
protectedRouter.route('/dev-server', devServerRouter);
|
||||
protectedRouter.route('/dock', dockRouter);
|
||||
protectedRouter.route('/integrations', integrationsRouter);
|
||||
|
||||
Reference in New Issue
Block a user