···2929 return err
3030 }
31313232+ if *streamerName == "" {
3333+ return fmt.Errorf("streamer name is required")
3434+ }
3535+3236 secpSigner, _ := secp256k1.PrivKeyFromBytes(keyBs)
3337 if secpSigner == nil {
3438 return fmt.Errorf("invalid key")
+5-5
pkg/cmd/streamplace.go
···8383 return Sign(context.Background())
8484 }
85858686+ if len(os.Args) > 1 && os.Args[1] == "whip" {
8787+ return WHIP()
8888+ }
8989+8690 if len(os.Args) > 1 && os.Args[1] == "self-test" {
8791 err := media.RunSelfTest(context.Background())
8892 if err != nil {
···122126 fs.StringVar(&cli.AppBundleID, "app-bundle-id", "", "bundle id of an app that we facilitate oauth login for")
123127 fs.StringVar(&cli.StreamerName, "streamer-name", "", "name of the person streaming from this streamplace node")
124128 fs.StringVar(&cli.FrontendProxy, "dev-frontend-proxy", "", "(FOR DEVELOPMENT ONLY) proxy frontend requests to this address instead of using the bundled frontend")
129129+ fs.BoolVar(&cli.WideOpen, "wide-open", false, "allow ALL streams to be uploaded to this node (not recommended for production)")
125130 cli.StringSliceFlag(fs, &cli.AllowedStreams, "allowed-streams", "", "if set, only allow these addresses or atproto DIDs to upload to this node")
126131 cli.StringSliceFlag(fs, &cli.Peers, "peers", "", "other streamplace nodes to replicate to")
127132 cli.DebugFlag(fs, &cli.Debug, "debug", "", "modified log verbosity for specific functions or files in form func=ToHLS:3,file=gstreamer.go:4")
128133 fs.BoolVar(&cli.TestStream, "test-stream", false, "run a built-in test stream on boot")
129134 fs.BoolVar(&cli.NoFirehose, "no-firehose", false, "disable the bluesky firehose")
130130- doValidate := fs.Bool("validate", false, "validate media")
131135 verbosity := fs.String("v", "3", "log verbosity level")
132136 fs.StringVar(&cli.RelayHost, "relay-host", "wss://bsky.network", "websocket url for relay firehose")
133137 fs.Bool("insecure", false, "DEPRECATED, does nothing.")
···166170 "runtime.Version", runtime.Version())
167171 if *version {
168172 return nil
169169- }
170170-171171- if *doValidate {
172172- return media.ValidateMedia(ctx)
173173 }
174174175175 aqhttp.UserAgent = fmt.Sprintf("streamplace/%s", build.Version)
···122122 return c
123123}
124124125125+func (mm *MediaManager) UnsubscribeSegment(ctx context.Context, user string, ch <-chan string) {
126126+ mm.mp4subsmut.Lock()
127127+ defer mm.mp4subsmut.Unlock()
128128+ for i, c := range mm.mp4subs[user] {
129129+ if c == ch {
130130+ mm.mp4subs[user] = append(mm.mp4subs[user][:i], mm.mp4subs[user][i+1:]...)
131131+ break
132132+ }
133133+ }
134134+}
135135+125136// subscribe to the latest segments from a given user for livestreaming purposes
126137func (mm *MediaManager) PublishSegment(ctx context.Context, user, file string) {
127138 mm.mp4subsmut.Lock()
+4-1
pkg/media/media_signer_ext.go
···6868 "--streamer", ms.streamer,
6969 "--start-time", fmt.Sprintf("%d", start))
70707171+ // overwrite so that our subprocesses don't do their own leak checking
7272+ cmd.Env = append(os.Environ(), "LD_PRELOAD=")
7373+7174 // Set up pipes for stdin and stdout
7275 stdin, err := cmd.StdinPipe()
7376 if err != nil {
···8790 // Copy input to stdin
8891 _, err = io.Copy(stdin, input)
8992 if err != nil {
9090- return nil, fmt.Errorf("failed to write to stdin: %w", err)
9393+ return nil, fmt.Errorf("failed to write to stdin: %w stderr=%s", err, stderr.String())
9194 }
9295 stdin.Close()
9396