diff options
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/transport.js')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/transport.js | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/transport.js b/packages/meshbay-hub/src/meshbay_hub/static/transport.js index e0e4a64..4f8e3b5 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/transport.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/transport.js @@ -620,6 +620,23 @@ class MeshBayTransport { } /** + * Server-side transcode of a Music-app file the browser's own <audio> + * element cannot decode at all (WMA, Musepack) into AAC/M4A. Returns + * `{ hash, size, mime }` — the *cache* hash to pull through the normal + * file_req/chunk path (fetchChunk/pipelinedDownload), not the file's own + * id, the same indirection already used for a TMDB poster or a + * MusicBrainz cover. Cached node-side after the first call, but ffmpeg + * still has to run at least once and a transcode slot can be busy, so + * this gets a longer timeout than the metadata lookups above. + */ + async requestAudioTranscode(fileId) { + const msg = await this._sendAndWait( + { type: 'audio_transcode_req', v: '0.9', file_id: fileId }, 120000); + if (msg.type === 'error') throw new Error(msg.detail); + return msg; + } + + /** * Set/clear the node-wide MusicBrainz contact string — the User-Agent * identity MusicBrainz's usage policy asks for, not a credential (there * is none, docs/musicbay.md §3.1). Signed like setTmdbConfig: this turns @@ -1386,6 +1403,9 @@ class MeshBayTransport { // search box can have more than one of these in flight at once. : obj.type === 'season_meta_req' ? `season_meta:${obj.tmdb_id}:${obj.season}` : obj.type === 'tmdb_search_req' ? `tmdb_search:${obj.media_type}:${obj.query}` + // Same reordering hazard as media_meta_req: the player prefetches + // the next track while the current one may still be transcoding. + : obj.type === 'audio_transcode_req' ? `audio_transcode:${obj.file_id}` : null, resolve: (msg) => { clearTimeout(timeout); this._pending.delete(id); resolve(msg); }, reject: (err) => { clearTimeout(timeout); this._pending.delete(id); reject(err); }, @@ -1641,6 +1661,17 @@ class MeshBayTransport { return; } + // Same reasoning as music_meta_resp: keyed, not arrival-order — the + // player can have a transcode of the current track and a prefetch of + // the next one in flight together. + if (msg.type === 'audio_transcode_resp') { + const key = `audio_transcode:${msg.file_id}`; + for (const [, handler] of this._pending) { + if (handler._key === key) { handler.resolve(msg); return; } + } + return; + } + // Same reasoning as media_meta_resp: keyed, not arrival-order, and // "nobody's waiting any more" must not fall through either. if (msg.type === 'season_meta_resp') { |