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:
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)
+ }
+}