Live video on the AT Protocol
1package cmd
2
3import (
4 "context"
5 "fmt"
6 "io"
7 "os"
8 "path/filepath"
9
10 "stream.place/streamplace/pkg/aqio"
11 "stream.place/streamplace/pkg/config"
12 "stream.place/streamplace/pkg/gstinit"
13 "stream.place/streamplace/pkg/log"
14 "stream.place/streamplace/pkg/media"
15)
16
17func Combine(ctx context.Context, build *config.BuildFlags, allArgs []string) error {
18 gstinit.InitGST()
19 cli := &config.CLI{Build: build}
20 fs := cli.NewFlagSet("streamplace combine")
21 debugDir := fs.String("debug-dir", "", "directory to write debug files to")
22
23 err := cli.Parse(fs, allArgs)
24 if err != nil {
25 return err
26 }
27 if *debugDir != "" {
28 err := os.MkdirAll(*debugDir, 0755)
29 if err != nil {
30 return fmt.Errorf("failed to create debug directory: %w", err)
31 }
32 }
33 log.Debug(context.Background(), "combine command: starting", "args", fs.Args())
34 ctx = log.WithDebugValue(ctx, cli.Debug)
35 cryptoSigner, err := createSigner(ctx, cli)
36 if err != nil {
37 return err
38 }
39 ms, err := media.MakeMediaSigner(ctx, cli, "combine", cryptoSigner, nil)
40 if err != nil {
41 return err
42 }
43 args := fs.Args()
44 outFile := args[0]
45 inputs := args[1:]
46 log.Log(ctx, "combining segments", "outFile", outFile, "inputs", inputs)
47 outFd, err := os.Create(outFile)
48 if err != nil {
49 return err
50 }
51 defer outFd.Close()
52 inputFds := make([]io.ReadSeeker, len(inputs))
53 for i, input := range inputs {
54 fd, err := os.Open(input)
55 if err != nil {
56 return err
57 }
58 defer fd.Close()
59 inputFds[i] = fd
60 }
61 err = media.CombineSegments(ctx, inputFds, ms, outFd)
62 if err != nil {
63 return err
64 }
65 err = CheckCombined(ctx, cli, outFd, *debugDir)
66 if err != nil {
67 return err
68 }
69 return nil
70}
71
72func CheckCombined(ctx context.Context, cli *config.CLI, inFD io.ReadWriteSeeker, debugDir string) error {
73 _, err := inFD.Seek(0, io.SeekStart)
74 if err != nil {
75 return err
76 }
77 err = media.SplitSegments(ctx, cli, inFD, func(fname string) media.ReadWriteSeekCloser {
78 if debugDir == "" {
79 return aqio.NewReadWriteSeeker([]byte{})
80 }
81 fd, err := os.Create(filepath.Join(debugDir, fname))
82 if err != nil {
83 panic(fmt.Errorf("failed to create debug file: %w", err))
84 }
85 log.Log(ctx, "created debug file", "path", filepath.Join(debugDir, fname))
86 return fd
87 })
88 if err != nil {
89 return err
90 }
91 return nil
92}