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/media"
16)
17
18func Sign(ctx context.Context) error {
19 fs := flag.NewFlagSet("streamplace", flag.ExitOnError)
20 certPath := fs.String("cert", "", "path to the certificate file")
21 key := fs.String("key", "", "base58-encoded secp256k1 private key")
22 streamerName := fs.String("streamer", "", "streamer name")
23 taURL := fs.String("ta-url", "http://timestamp.digicert.com", "timestamp authority server for signing")
24 startTime := fs.Int64("start-time", 0, "start time of the stream")
25 if err := fs.Parse(os.Args[2:]); err != nil {
26 return err
27 }
28
29 keyBs, err := base58.Decode(*key)
30 if err != nil {
31 return err
32 }
33
34 if *streamerName == "" {
35 return fmt.Errorf("streamer name is required")
36 }
37
38 secpSigner, _ := secp256k1.PrivKeyFromBytes(keyBs)
39 if secpSigner == nil {
40 return fmt.Errorf("invalid key")
41 }
42 signer := secpSigner.ToECDSA()
43
44 certBs, err := os.ReadFile(*certPath)
45 if err != nil {
46 return err
47 }
48
49 pub, err := aqpub.FromPublicKey(signer.Public().(*ecdsa.PublicKey))
50 if err != nil {
51 return err
52 }
53
54 ms := &media.MediaSignerLocal{
55 Signer: signer,
56 Cert: certBs,
57 StreamerName: *streamerName,
58 TAURL: *taURL,
59 AQPub: pub,
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}