Documentation
¶
Overview ¶
Package localstream wraps the io.ReadSeeker of a local mounted file so the server can do two things at once while a video plays:
- measure how fast bytes are actually pulled from the underlying mount (a throughput indicator for the UI — crucial on rclone/Google-Drive mounts where a play silently fetches over the network), and
- read ahead in large, aligned blocks so ffmpeg/ServeContent don't issue many tiny Range reads that an rclone FUSE mount penalises.
A single Session covers both the direct-play path (it is an io.ReadSeeker, fed to http.ServeContent) and the HLS path (the transcode package wraps it in its own atomic readSeekerContent). The Registry keys sessions so the transfer-status endpoint can find the live throughput for a given file.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ReadSeekCloser ¶
type ReadSeekCloser interface {
io.ReadSeeker
io.Closer
}
ReadSeekCloser is the underlying file handle a Session owns (an *os.File satisfies it). The Session closes it when the Registry reaps the session.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry tracks live read sessions keyed by a caller-chosen string (built from mount/path/user). It hands out Sessions, refcounts the direct-play path, and reaps idle sessions so a closed player doesn't leak file handles.
func NewRegistry ¶
NewRegistry builds a Registry whose sessions read ahead readaheadMB at a time (0 → 16 MiB default) and starts the idle reaper.
func (*Registry) Close ¶
func (r *Registry) Close()
Close stops the reaper and closes every live session.
func (*Registry) OpenShared ¶
func (r *Registry) OpenShared(key string, f ReadSeekCloser, size int64) *Session
OpenShared returns the Session for key, creating it from f if absent and reusing (and closing the duplicate f) if present. Use this for sessions that outlive a single request (the HLS transcode source, deduped by key): the caller does NOT Release — the reaper closes it when ffmpeg stops pulling.
func (*Registry) OpenSolo ¶
func (r *Registry) OpenSolo(key string, f ReadSeekCloser, size int64) *Session
OpenSolo returns a fresh Session bound to its own f and registers it under key for status lookup. Use this for the direct-play path, where concurrent http.ServeContent requests must NOT share a single cursor. Pair every OpenSolo with a deferred Release(key, sess).
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session wraps one open file. Read/Seek are mutex-guarded so it is safe to share across the (already serialised) HLS reader and concurrent status reads. Only bytes fetched from the underlying file are metered — buffer replays are not, so the rate reflects real mount I/O, not cache hits.
func (*Session) Read ¶
Read serves from the read-ahead buffer when possible; otherwise it refills the buffer with one large aligned read at the current position. Implements io.Reader.