WIP: hacking

This commit is contained in:
Rob Watson 2020-07-05 08:15:58 +02:00
parent 5e7bfa72dd
commit 689929b27a
2 changed files with 121 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/segmento

120
main.go Normal file
View File

@ -0,0 +1,120 @@
package main
import (
"flag"
"fmt"
"io"
"log"
"net/http"
"os"
"time"
"github.com/tcolgate/mp3"
)
// TODO what should be the behaviour when adding a Frame to a Segment causes it to over-shoot
// the TargetDuration?
// should the frame be partially added, or not added at all?
// typical frame duration 36ms
type Segment struct {
TargetDuration time.Duration
Duration time.Duration
Data []byte
}
func newSegment(capacity int) *Segment {
return &Segment{
Data: make([]byte, 0, capacity),
}
}
func (s *Segment) Write(p []byte) (n int, err error) {
fmt.Println("write", len(p), "bytes")
return len(p), nil
}
type MP3HTTPSegmenter struct {
decoder *mp3.Decoder
}
func (s *MP3HTTPSegmenter) Segment(r io.Reader) (chan Segment, error) {
c := make(chan Segment)
go func() {
d := mp3.NewDecoder(r)
var (
v mp3.Frame
skipped int
)
for {
if err := d.Decode(&v, &skipped); err != nil {
log.Fatal(err)
}
fmt.Println("decoded frame of", v.Size(), "bytes, duration", v.Duration(), ", skipped", skipped, "bytes")
}
}()
return c, nil
}
func newMP3HTTPSegmenter() *MP3HTTPSegmenter {
return &MP3HTTPSegmenter{}
}
// TODO
// A Segmenter class which allows the passing in of a Reader
// i.e.
// Segment(r io.Reader) (chan *Segment, error)
// This will create an mp3.NewDecoder(r) and store the returned decoder.
// As the Reader is read, the Segmenter will publish a stream of SegmentEvents
func main() {
// TODO accept some flags with:
// URL - source of stream
// TargetLength - length of segments in seconds
// Output
// -d some_dir/ => output playlist and chunks to this directory, cleaning up old files from time to time.
// -b 0.0.0.0:3000 => serve playlist and chunks from an HTTP server bound to this address
var url string
flag.StringVar(&url, "url", "", "URL of MP3 stream")
flag.Parse()
if url == "" {
log.Println("Invalid arguments")
flag.PrintDefaults()
os.Exit(-1)
}
log.Println("Open URL:", url)
client := &http.Client{}
resp, err := client.Get(url)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
segmenter := newMP3HTTPSegmenter()
segments, err := segmenter.Segment(resp.Body)
if err != nil {
log.Fatal(err)
}
go func() {
for segment := range segments {
log.Println("got segment", segment)
}
}()
time.Sleep(10 * time.Second)
log.Println("exiting")
}