github.com/0chain/gosdk@v1.17.11/zboxcore/sdk/m3u8.go (about) 1 package sdk 2 3 import ( 4 "bytes" 5 "io" 6 "os" 7 "path/filepath" 8 "strconv" 9 "time" 10 11 "github.com/0chain/gosdk/core/sys" 12 ) 13 14 // #EXTM3U 15 // #EXT-X-VERSION:3 16 // #EXT-X-TARGETDURATION:5 17 // #EXT-X-MEDIA-SEQUENCE:17 18 // #EXTINF:5.000000, 19 // tv17.ts 20 // #EXTINF:5.000000, 21 // tv18.ts 22 // #EXTINF:5.000000, 23 // tv19.ts 24 // #EXTINF:5.000000, 25 // tv20.ts 26 // #EXTINF:5.000000, 27 // tv21.ts 28 29 // MediaPlaylist queue-based m3u8 playlist 30 type MediaPlaylist struct { 31 dir string 32 delay int 33 34 writer M3u8Writer 35 36 // wait wait to play 37 wait []string 38 39 next chan string 40 seq int 41 } 42 43 // NewMediaPlaylist create media playlist(.m3u8) 44 func NewMediaPlaylist(delay int, dir string, writer M3u8Writer) *MediaPlaylist { 45 m3u8 := &MediaPlaylist{ 46 dir: dir, 47 delay: delay, 48 wait: make([]string, 0, 5), 49 next: make(chan string, 100), 50 seq: 0, 51 writer: writer, 52 } 53 54 m3u8.writer.Write([]byte("#EXTM3U\n")) //nolint 55 m3u8.writer.Write([]byte("#EXT-X-VERSION:3\n")) //nolint 56 m3u8.writer.Write([]byte("#EXT-X-TARGETDURATION:" + strconv.Itoa(delay) + "\n")) //nolint 57 m3u8.writer.Sync() //nolint 58 go m3u8.Play() 59 60 return m3u8 61 } 62 63 // Append append new item into playlist 64 func (m *MediaPlaylist) Append(item string) { 65 m.next <- item 66 } 67 68 // Play start to play the contents of the playlist with 1 second buffer between each item 69 func (m *MediaPlaylist) Play() { 70 71 for { 72 73 item := <-m.next 74 75 _, err := sys.Files.Stat(filepath.Join(m.dir, item)) 76 77 if err == nil { 78 if len(m.wait) < 5 { 79 m.seq = 1 80 m.wait = append(m.wait, "."+string(os.PathSeparator)+item) 81 } else { 82 m.seq++ 83 m.wait = append(m.wait[1:], "."+string(os.PathSeparator)+item) 84 } 85 86 m.flush() 87 } 88 89 sys.Sleep(1 * time.Second) 90 91 } 92 93 } 94 95 // flush try flush new ts file into playlist. return true if list is full 96 func (m *MediaPlaylist) flush() { 97 98 m.writer.Truncate(0) //nolint 99 m.writer.Seek(0, 0) //nolint 100 m.writer.Write(m.Encode()) //nolint 101 m.writer.Sync() //nolint 102 103 } 104 105 // Encode encode m3u8 106 func (m *MediaPlaylist) Encode() []byte { 107 var buf bytes.Buffer 108 109 duration := strconv.Itoa(m.delay) 110 111 buf.WriteString("#EXTM3U\n") 112 buf.WriteString("#EXT-X-VERSION:3\n") 113 buf.WriteString("#EXT-X-TARGETDURATION:" + duration + "\n") 114 buf.WriteString("#EXT-X-MEDIA-SEQUENCE:" + strconv.Itoa(m.seq) + "\n") 115 116 for _, it := range m.wait { 117 buf.WriteString("#EXTINF:" + duration + ",\n") 118 buf.WriteString(it + "\n") 119 } 120 121 return buf.Bytes() 122 } 123 124 // String implement Stringer 125 func (m *MediaPlaylist) String() string { 126 return string(m.Encode()) 127 } 128 129 // M3u8Writer m3u8 writer 130 type M3u8Writer interface { 131 io.WriteSeeker 132 Truncate(size int64) error 133 Sync() error 134 }