Helper tool for stitching together livestream VOD segments and uploading them to YouTube!

fix crummy ffprobe json output handling

+42 -16
+14 -10
main.go
··· 6 6 "encoding/json" 7 7 "fmt" 8 8 "log" 9 + "math" 9 10 "net/http" 10 11 "os" 11 12 "path" ··· 247 248 // concatenate VOD segments into full VOD 248 249 fullVodExists := func () bool { 249 250 // check if full VOD already exists with expected duration 250 - if fullVodProbe, err := scanner.ProbeSegment(video.Filename); err != nil { 251 - var totalLength float64 = 0 252 - for _, filename := range vodFiles { 253 - probe, err := scanner.ProbeSegment(filename) 254 - if err != nil { continue } 255 - totalLength += probe.Format.Duration 256 - } 257 - return fullVodProbe.Format.Duration == totalLength 251 + fullVodProbe, err := scanner.ProbeSegment(video.Filename) 252 + if err != nil { return false } 253 + video.SizeBytes = fullVodProbe.Format.Size 254 + var totalLength float64 = 0 255 + 256 + for _, filename := range vodFiles { 257 + probe, err := scanner.ProbeSegment(path.Join(metadata.FootageDir, filename)) 258 + if err != nil { continue } 259 + totalLength += probe.Format.Duration 258 260 } 259 - return false 261 + return math.Abs(fullVodProbe.Format.Duration - totalLength) < float64(0.1) 260 262 }() 261 - if !fullVodExists { 263 + if fullVodExists { 264 + log.Print("Full VOD appears to already exist- uploading this file...") 265 + } else { 262 266 video.SizeBytes, err = vid.ConcatVideo(video, vodFiles, verbose) 263 267 if err != nil { 264 268 log.Fatalf("Failed to concatenate VOD segments: %v", err)
+28 -6
scanner/scanner.go
··· 4 4 "encoding/json" 5 5 "os" 6 6 "path" 7 + "strconv" 7 8 "strings" 8 9 "time" 9 10 ··· 28 29 Category *Category `toml:"category" comment:"(Optional) Category details, for additional credits."` 29 30 } 30 31 31 - ffprobeFormat struct { 32 + FFprobeFormat struct { 32 33 Duration float64 `json:"duration"` 33 34 Size int64 `json:"size"` 34 35 } 35 36 36 - ffprobeOutput struct { 37 - Format ffprobeFormat `json:"format"` 37 + FFprobeOutput struct { 38 + Format FFprobeFormat `json:"format"` 38 39 } 39 40 ) 40 41 ··· 58 59 return files, nil 59 60 } 60 61 61 - func ProbeSegment(filename string) (*ffprobeOutput, error) { 62 + func ProbeSegment(filename string) (*FFprobeOutput, error) { 62 63 out, err := ffmpeg_go.Probe(filename) 63 64 if err != nil { return nil, err } 64 65 65 - probe := ffprobeOutput{} 66 + type ( 67 + RawFFprobeFormat struct { 68 + // these being strings upsets me immensely 69 + Duration string `json:"duration"` 70 + Size string `json:"size"` 71 + } 72 + RawFFprobeOutput struct { 73 + Format RawFFprobeFormat `json:"format"` 74 + } 75 + ) 76 + 77 + probe := RawFFprobeOutput{} 66 78 err = json.Unmarshal([]byte(out), &probe) 67 79 if err != nil { return nil, err } 68 80 69 - return &probe, nil 81 + duration, err := strconv.ParseFloat(probe.Format.Duration, 64) 82 + if err != nil { return nil, err } 83 + size, err := strconv.ParseInt(probe.Format.Size, 10, 0) 84 + if err != nil { return nil, err } 85 + 86 + return &FFprobeOutput{ 87 + Format: FFprobeFormat{ 88 + Duration: duration, 89 + Size: size, 90 + }, 91 + }, nil 70 92 } 71 93 72 94 func ReadMetadata(directory string) (*Metadata, error) {