Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ShellReader ¶
type ShellReader struct {
// contains filtered or unexported fields
}
ShellReader spawns a ffmpeg subprocess, exposes its stdout as a Reader, captures the tail of stderr in a fixed-size ring, and cleans up when the context is canceled or the process exits.
ShellReader is safe to use across goroutines for Close and Err. Read must be serialized by a single consumer (the convention for io.Reader).
We manage the stdout pipe ourselves (os.Pipe + cmd.Stdout = pw) rather than using cmd.StdoutPipe so that cmd.Wait does NOT close the read end out from under us. That's a documented stdlib gotcha — when Wait fires the moment the child exits, StdoutPipe closes the read end immediately, discarding any unread bytes in the kernel pipe buffer (i.e. the last chunk of audio the streamer hadn't paced through yet). With a manual pipe, reads drain naturally to io.EOF after the child's pw closes.
func NewShellReader ¶
func NewShellReader(parent context.Context, program string, args []string, log *slog.Logger) (*ShellReader, error)
NewShellReader spawns program with args and starts the process. The returned reader streams stdout. If the program cannot be started, ErrFFmpegSpawn is returned wrapped.
func (*ShellReader) Close ¶
func (r *ShellReader) Close() error
Close terminates the subprocess (if still running) and our copy of the read end of the pipe, then waits for the reaper. Closing the read end unblocks any pending Read in-flight by another goroutine.
func (*ShellReader) Done ¶
func (r *ShellReader) Done() <-chan struct{}
Done is closed when the subprocess exits.
func (*ShellReader) Err ¶
func (r *ShellReader) Err() error
Err returns the process exit error (after Done is closed).