// Copyright 2020, Chef. All rights reserved. // https://github.com/q191201771/lal // // Use of this source code is governed by a MIT-style license // that can be found in the License file. // // Author: Chef (191201771@qq.com) package hls import ( "bytes" "fmt" "strconv" ) // @param content 需写入文件的内容 // @param filename m3u8文件名 // @param filenameBak m3u8临时文件名 // func writeM3u8File(content []byte, filename string, filenameBak string) error { if err := fslCtx.WriteFile(filenameBak, content, 0666); err != nil { return err } return fslCtx.Rename(filenameBak, filename) } // 如果当前duration比原m3u8文件的`EXT-X-TARGETDURATION`大,则更新`EXT-X-TARGETDURATION`的值 // // @param content 原m3u8文件的内容 // @param currDuration 当前duration // // @return 处理后的m3u8文件内容 func updateTargetDurationInM3u8(content []byte, currDuration int) ([]byte, error) { l := bytes.Index(content, []byte("#EXT-X-TARGETDURATION:")) if l == -1 { return content, ErrHls } r := bytes.Index(content[l:], []byte{'\n'}) if r == -1 { return content, ErrHls } oldDurationStr := bytes.TrimPrefix(content[l:l+r], []byte("#EXT-X-TARGETDURATION:")) oldDuration, err := strconv.Atoi(string(oldDurationStr)) if err != nil { return content, err } if currDuration > oldDuration { tmpContent := make([]byte, l) copy(tmpContent, content[:l]) tmpContent = append(tmpContent, []byte(fmt.Sprintf("#EXT-X-TARGETDURATION:%d", currDuration))...) tmpContent = append(tmpContent, content[l+r:]...) content = tmpContent } return content, nil } // @param content 传入m3u8文件内容 // // @return durationSec m3u8中所有ts的时间总和。注意,使用的是m3u8文件中描述的ts时间,而不是读取ts文件中实际音视频数据的时间。 // func CalcM3u8Duration(content []byte) (durationSec float64, err error) { lines := bytes.Split(content, []byte{'\n'}) for _, line := range lines { if bytes.HasPrefix(line, []byte("#EXTINF:")) { line = bytes.TrimSpace(line) v := bytes.TrimSuffix(bytes.TrimPrefix(line, []byte("#EXTINF:")), []byte{','}) v = bytes.TrimSpace(v) vv, err := strconv.ParseFloat(string(v), 64) if err != nil { return durationSec, err } durationSec += vv } } return }