Live video on the AT Protocol
79
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v0.7.27 174 lines 3.7 kB view raw
1package main 2 3import ( 4 "encoding/json" 5 "errors" 6 "flag" 7 "fmt" 8 "io" 9 "log" 10 "math" 11 "os" 12 "time" 13 14 "stream.place/streamplace/pkg/rtcrec" 15) 16 17func main() { 18 err := Start() 19 if err != nil { 20 log.Fatal(err) 21 } 22} 23 24func Start() error { 25 if len(os.Args) > 1 && os.Args[1] == "decode" { 26 return Decode() 27 } 28 if len(os.Args) > 1 && os.Args[1] == "trim" { 29 return Trim() 30 } 31 return fmt.Errorf("unknown command: %s", os.Args[1]) 32} 33 34func Trim() error { 35 var startDuration time.Duration 36 flag.DurationVar(&startDuration, "start", 0, "timestamp where we should start our clip") 37 var endDuration time.Duration 38 flag.DurationVar(&endDuration, "end", 0, "timestamp where we should end our clip") 39 var inPath string 40 flag.StringVar(&inPath, "in-path", "", "path to the file to decode") 41 var outPath string 42 flag.StringVar(&outPath, "out-path", "", "path to the file to write the trimmed file to") 43 err := flag.CommandLine.Parse(os.Args[2:]) 44 if err != nil { 45 return err 46 } 47 if startDuration == 0 && endDuration == 0 { 48 return fmt.Errorf("start or end duration is required (otherwise, you know, the cp command is right there)") 49 } 50 if inPath == "" { 51 return fmt.Errorf("in-path is required") 52 } 53 if outPath == "" { 54 return fmt.Errorf("out-path is required") 55 } 56 inFile, err := os.Open(inPath) 57 if err != nil { 58 return err 59 } 60 defer inFile.Close() 61 outFile, err := os.Create(outPath) 62 if err != nil { 63 return err 64 } 65 defer outFile.Close() 66 dec, err := rtcrec.MakeWebRTCDecoder(inFile) 67 if err != nil { 68 return err 69 } 70 encoder, err := rtcrec.MakeWebRTCEncoder(outFile) 71 if err != nil { 72 return err 73 } 74 var startCutoff *time.Time 75 var endCutoff *time.Time 76 if startDuration == 0 { 77 startCutoff = &time.Time{} 78 } 79 if endDuration == 0 { 80 t := time.Unix(math.MaxInt64, 0) 81 endCutoff = &t 82 } 83 included := 0 84 dropped := 0 85 for { 86 ev, err := dec.Next() 87 if errors.Is(err, io.EOF) { 88 break 89 } 90 if startCutoff == nil { 91 t := ev.Time.Add(startDuration) 92 startCutoff = &t 93 } 94 if endCutoff == nil { 95 t := ev.Time.Add(endDuration) 96 endCutoff = &t 97 } 98 // we only rewrite trackread events 99 if ev.TrackRead == nil { 100 if ev.Time.Before(*endCutoff) { 101 // included++ 102 encoder.Event(*ev) 103 } 104 continue 105 } 106 if ev.Time.Before(*startCutoff) || ev.Time.After(*endCutoff) { 107 // fmt.Printf("dropped: %s < %s\n", ev.Time.Format(time.RFC3339Nano), cutoff.Format(time.RFC3339Nano)) 108 dropped++ 109 continue 110 } 111 included++ 112 ev.Time = ev.Time.Add(-startDuration) 113 encoder.Event(*ev) 114 } 115 fmt.Printf("included: %d, dropped: %d\n", included, dropped) 116 return nil 117} 118 119func Decode() error { 120 var path string 121 flag.StringVar(&path, "path", "", "path to the file to decode") 122 flag.Parse() 123 if path == "" { 124 return fmt.Errorf("path is required") 125 } 126 return DecodeFile(path) 127} 128 129func DecodeFile(path string) error { 130 f, err := os.Open(path) 131 if err != nil { 132 return err 133 } 134 defer f.Close() 135 dec, err := rtcrec.MakeWebRTCDecoder(f) 136 if err != nil { 137 return err 138 } 139 for { 140 ev, err := dec.Next() 141 if errors.Is(err, io.EOF) { 142 return nil 143 } 144 if err != nil { 145 return err 146 } 147 if ev.TrackRead != nil { 148 // spitting out the data as base64 is pointless, replace with a label 149 n := len(ev.TrackRead.Data) 150 byteString := fmt.Sprintf("%d bytes", n) 151 bs, err := json.Marshal(ev) 152 if err != nil { 153 return err 154 } 155 var m map[string]any 156 err = json.Unmarshal(bs, &m) 157 if err != nil { 158 return err 159 } 160 m["trackRead"].(map[string]any)["data"] = byteString 161 bs, err = json.Marshal(m) 162 if err != nil { 163 return err 164 } 165 fmt.Println(string(bs)) 166 } else { 167 bs, err := json.Marshal(ev) 168 if err != nil { 169 return err 170 } 171 fmt.Println(string(bs)) 172 } 173 } 174}