Live video on the AT Protocol
1package cmd
2
3import (
4 "bytes"
5 "context"
6 "crypto/ecdsa"
7 "fmt"
8 "io"
9 "os"
10
11 "github.com/decred/dcrd/dcrec/secp256k1"
12 "github.com/mr-tron/base58"
13 "stream.place/streamplace/pkg/crypto/aqpub"
14 "stream.place/streamplace/pkg/log"
15 "stream.place/streamplace/pkg/media"
16)
17
18func Sign(ctx context.Context, certPath string, key string, streamerName string, taURL string, startTime int64, manifestJSON string) error {
19 log.Debug(ctx, "Sign command: starting",
20 "streamer", streamerName,
21 "startTime", startTime,
22 "hasManifest", len(manifestJSON) > 0)
23
24 keyBs, err := base58.Decode(key)
25 if err != nil {
26 return err
27 }
28
29 if streamerName == "" {
30 return fmt.Errorf("streamer name is required")
31 }
32
33 secpSigner, _ := secp256k1.PrivKeyFromBytes(keyBs)
34 if secpSigner == nil {
35 return fmt.Errorf("invalid key")
36 }
37 signer := secpSigner.ToECDSA()
38
39 certBs, err := os.ReadFile(certPath)
40 if err != nil {
41 return err
42 }
43
44 pub, err := aqpub.FromPublicKey(signer.Public().(*ecdsa.PublicKey))
45 if err != nil {
46 return err
47 }
48
49 ms := &media.MediaSignerLocal{
50 Signer: signer,
51 Cert: certBs,
52 StreamerName: streamerName,
53 TAURL: taURL,
54 AQPub: pub,
55 PrebuiltManifest: []byte(manifestJSON), // Pass the manifest from parent process
56 }
57
58 if len(manifestJSON) > 0 {
59 log.Debug(ctx, "Sign command: using provided manifest", "manifestLength", len(manifestJSON))
60 }
61
62 inputBs, err := io.ReadAll(os.Stdin)
63 if err != nil {
64 return err
65 }
66
67 mp4, err := ms.SignMP4(ctx, bytes.NewReader(inputBs), startTime)
68 if err != nil {
69 return err
70 }
71 _, err = io.Copy(os.Stdout, bytes.NewReader(mp4))
72 if err != nil {
73 return err
74 }
75
76 return nil
77}