Document device media paths and direct transfer requirements
This commit is contained in:
69
docs/p2p-transfer.md
Normal file
69
docs/p2p-transfer.md
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
# Direct device media transfers
|
||||||
|
|
||||||
|
## Existing paths (audit before implementation)
|
||||||
|
|
||||||
|
| Path | Existing media-byte route | Relevant code |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Paired remote | Controls only; the host plays its own source. No existing file-send action. | `frontend/app.js` Remote; `server/remote.js` |
|
||||||
|
| Presenter and OBS | Lyrics, timing and metadata only; neither currently plays host media. | Presenter and overlay modules; remote relay |
|
||||||
|
| Watch Party playback | Each guest loads independently through normal server/YouTube playback, unless already saved locally. | Party `applyState`, `Player.loadVideo`; `server/party.js` |
|
||||||
|
| Watch Party voice | Direct WebRTC audio; server forwards SDP/ICE only. | Party voice mesh, party `rtc` relay |
|
||||||
|
| On other devices / failed playback | Existing verified-file DataChannel download, 64 KiB frames, SHA-256 validation, worker writes OPFS. Only offered after server failure in playback. | `p2p-transfer.js`, `p2p-recv-worker.js`, `getFromPeers` |
|
||||||
|
| Save / preload | Server download first, then OPFS. | `preload`, `API.cacheDownload`, download endpoints |
|
||||||
|
| Export to Files / Photos | Local OPFS first, server URL next, peer fallback last. Native share is an OS export, not paired-device transfer. | `exportToDevice`, `export.js` |
|
||||||
|
| Profile / playlist share and send | Metadata only. Sending a playlist does not transfer its media files. | Profile/playlist sync APIs |
|
||||||
|
| Verify & share | Explicit device upload to server intake; hash and media validation admit it into the server cache. | `P2PClient.contribute`, `p2p-intake.js` |
|
||||||
|
| Automatic rehydration | Server requests a holder to upload its full file to intake. This is an implicit media-byte server path. | `createRehydrator`, client `upload-request` handler |
|
||||||
|
| Admin uploads / original YouTube downloads | Intentional server ingestion of original media; separate from direct device transfer. | Upload and media-cache endpoints |
|
||||||
|
| VLC / external player URLs | HTTP server media URLs; these players cannot consume this application's DataChannel. | External player actions |
|
||||||
|
|
||||||
|
The current file protocol has no resume: its receiver truncates partial files and
|
||||||
|
removes them on failure. Connection timeout is 20 seconds per holder. Device
|
||||||
|
signalling authenticates a device, but does not constrain its destination to a
|
||||||
|
verified profile or paired room. Profile names supplied at device registration
|
||||||
|
are not proof of profile membership. Existing server-verified holdings also
|
||||||
|
exclude files whose bytes the server has never admitted.
|
||||||
|
|
||||||
|
## Implementation design
|
||||||
|
|
||||||
|
Reuse ordered RTCDataChannel transfers with public STUN only. The WebSocket
|
||||||
|
server carries bounded, validated signalling and metadata, never file chunks.
|
||||||
|
Pair authorization must come from an authenticated remote/party room or a
|
||||||
|
verified profile session, not an arbitrary client-supplied profile name.
|
||||||
|
|
||||||
|
A receiver explicitly accepts an invitation before saving. A cryptographically
|
||||||
|
random, expiring, one-use invitation binds sender, receiver and file identity;
|
||||||
|
subsequent signalling remains bound to that pair. Reject replay, mismatched
|
||||||
|
identities, binary WebSocket messages and unrecognized protocol fields.
|
||||||
|
|
||||||
|
Send 64 KiB chunks with bufferedAmount backpressure. Persist a partial OPFS file
|
||||||
|
and resume at its exact committed byte offset. Rehash the retained prefix before
|
||||||
|
continuing and verify total size and SHA-256 before promoting the file into the
|
||||||
|
saved store; only then record metadata. A changed hash/size cannot reuse a partial.
|
||||||
|
|
||||||
|
Use a 10-second connection deadline and an explicit, clearly labelled server
|
||||||
|
fallback offer. Direct mode must not silently rehydrate server media from a
|
||||||
|
device. Register “Direct device transfer (P2P)” in Settings, default on.
|
||||||
|
|
||||||
|
Party playback should request a host's saved file when announced, then play the
|
||||||
|
receiver's OPFS copy. Remote controls and presenter lyrics retain their existing
|
||||||
|
behaviour; add explicit receive/play actions rather than automatically starting
|
||||||
|
media in a control-only screen. A manual send action targets authenticated peers.
|
||||||
|
|
||||||
|
Ordinary faststart MP4 cannot safely be appended as arbitrary MediaSource chunks.
|
||||||
|
Progressive playback requires supported fragmented media and codec detection;
|
||||||
|
otherwise use the completed, verified file (including iOS). Do not claim that
|
||||||
|
raw MP4 chunks provide progressive playback.
|
||||||
|
|
||||||
|
## Verification required before release
|
||||||
|
|
||||||
|
Pure tests cover protocol parsing, chunk bounds, offsets, invitation replay and
|
||||||
|
pair authorization. A two-page localhost browser test must transfer real bytes
|
||||||
|
into OPFS through WebRTC and assert that server HTTP/WS logs contain only
|
||||||
|
signalling and metadata. Exercise interruption/resume and explicit fallback.
|
||||||
|
Review real iPhone foreground/background behaviour and restrictive NAT failure.
|
||||||
|
|
||||||
|
## Implementation status
|
||||||
|
|
||||||
|
This document records the pre-implementation audit and design. Transport,
|
||||||
|
authorization and UI changes described above are not yet implemented.
|
||||||
Reference in New Issue
Block a user