streaming

Media streaming and broadcast systems in Go
Log | Files | Refs | README | LICENSE

commit 69e6191557711b6dd82b524cd204458310fea746
parent 77cd9c1576a8929f7aed8cc9f81a8efca01130fd
Author: Oliver Lowe <o@olowe.co>
Date:   Fri, 17 May 2024 13:01:20 +1000

m3u8: implement basic playlist encoding/writing

This is enough to encode the simplest playlist from
test-streams.mux.dev. Plays ok in VLC, QuickTime, ffplay(1).

Diffstat:
Am3u8/write.go | 24++++++++++++++++++++++++
Am3u8/write_test.go | 34++++++++++++++++++++++++++++++++++
2 files changed, 58 insertions(+), 0 deletions(-)

diff --git a/m3u8/write.go b/m3u8/write.go @@ -0,0 +1,24 @@ +package m3u8 + +import ( + "fmt" + "io" + "time" +) + +func Encode(w io.Writer, p *Playlist) error { + fmt.Fprintln(w, "#EXTM3U") + fmt.Fprintf(w, "%s:%d\n", tagVersion, p.Version) + fmt.Fprintf(w, "%s:%s\n", tagPlaylistType, p.Type) + fmt.Fprintf(w, "%s:%d\n", tagTargetDuration, p.TargetDuration/time.Second) + for _, seg := range p.Segments { + us := seg.Duration / time.Microsecond + // we do .03f for the same precision as test-streams.mux.dev. + fmt.Fprintf(w, "%s:%.03f\n", tagSegmentDuration, float32(us)/1e6) + fmt.Fprintln(w, seg.URI) + } + if p.End { + fmt.Fprintln(w, tagEndList) + } + return nil +} diff --git a/m3u8/write_test.go b/m3u8/write_test.go @@ -0,0 +1,34 @@ +package m3u8 + +import ( + "bufio" + "bytes" + "testing" + "time" +) + +func TestEncodeSegDuration(t *testing.T) { + plist := &Playlist{ + Version: 7, + Segments: []Segment{{Duration: 9967 * time.Millisecond}}, + } + buf := &bytes.Buffer{} + if err := Encode(buf, plist); err != nil { + t.Fatal(err) + } + sc := bufio.NewScanner(buf) + var linenum = 1 + var found bool + want := "#EXTINF:9.967" + for sc.Scan() { + t.Log(sc.Text()) + if sc.Text() == want { + found = true + return + } + linenum++ + } + if !found { + t.Errorf("no matching segment duration %s", want) + } +}