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