Files
谢宇宁andClaude Opus 5.5 0fbdba5ccf Initial commit
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 11:47:47 +07:00

134 lines
3.6 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package m3u8
import (
"bytes"
"crypto/md5"
"encoding/hex"
"fmt"
"strconv"
"time"
"videoweb/pub/common/errors"
"videoweb/pub/common/utils"
"videoweb/pub/pubdef"
"videoweb/pub/storage/proxy"
"github.com/grafov/m3u8"
)
// transform m3u8文件转换,将不正确的m3u8文件,替换为正确的m3u8文件
// apiType(1:app,2:h5app,3:web)
func TransformEx(name string, cdnDomain, origDomain string, apiType int, authKey string) (
media *m3u8.MediaPlaylist, buff *bytes.Buffer, err error) {
if name == "" {
err = errors.MakeWithMsg(errors.M3u8FileName, "m3u8 file name is empty")
return
}
if cdnDomain == "" || origDomain == "" {
err = errors.MakeWithMsg(errors.DomainErr, "cdnDomain or origDomain is empty")
return
}
// 处理媒资库 桶1(v1) 桶2(v2) 桶3(v3)
mediaVerson := proxy.AppendsMediaS3Version(name)
if len(mediaVerson) > 0 {
name = mediaVerson + name
}
authKey = resolveTsAuthKey(authKey)
//log.Info("Test", log.Any("name", name), log.Any("cdnDomain", cdnDomain), log.Any("origDomain", origDomain), log.Any("authKey", authKey))
m3u8reader, err := readFromRedis(name, origDomain)
if err != nil {
return
}
p, t, err := m3u8.DecodeFrom(m3u8reader, false)
if err != nil {
err = errors.MakeWithErr(errors.M3u8Read, err)
return
}
apiPath := keyUri
if apiType == 2 {
apiPath = h5KeyUri
} else if apiType == 3 {
apiPath = webkeyUri
}
switch t {
case m3u8.MEDIA:
pl := p.(*m3u8.MediaPlaylist)
dirPath := utils.PathForInfo(name).Dir
media, err = makeTSList(pl, cdnDomain, dirPath, apiPath, authKey)
if err != nil {
return
}
buff = media.Encode()
case m3u8.MASTER:
mpl := p.(*m3u8.MasterPlaylist)
buff = mpl.Encode()
default:
err = errors.MakeWithMsg(errors.M3u8FileName, fmt.Sprintf("invalid m3u8 type %d", t))
}
return
}
// makeTSList 根据from,重新生成播放列表
func makeTSList(from *m3u8.MediaPlaylist, cdnDomain string,
dirPath string, apiPath string, authKey string) (
media *m3u8.MediaPlaylist, err error) {
media, err = m3u8.NewMediaPlaylist(from.WinSize(), from.Count())
if err != nil {
return
}
now := time.Now()
base := utils.JoinUrlPath(cdnDomain, dirPath)
for _, segment := range from.Segments {
if segment == nil {
continue
}
sg := new(m3u8.MediaSegment)
sg.URI = utils.JoinUrlPath(base, segment.URI)
if len(authKey) > 0 {
//生成鉴权url
urlPath := utils.JoinUrlPath(dirPath, segment.URI)
urlAuth := generateUrlAuth(now, urlPath, authKey)
sg.URI = sg.URI + urlAuth
}
sg.Title = segment.Title
sg.Duration = segment.Duration
if err = media.AppendSegment(sg); err != nil {
return
}
}
_ = media.SetDefaultKey("AES-128", apiPath, "", "", "")
media.Close()
return
}
// 生成鉴权url
func generateUrlAuth(now time.Time, path string, authKey string) string {
timestamp := now.Unix()
signStr := fmt.Sprintf("%s-%d-0-0-%s", path, timestamp, authKey)
md5Str := getMD5Sign(signStr)
// TS CDN 鉴权参数后追加应用标识,便于流量统计。
urlAuth := fmt.Sprintf("?md=%d-0-0-%s&c=%d", timestamp, md5Str, pubdef.AppId)
return urlAuth
}
// 生成鉴权url 七牛云
func generateUrlAuthQiniu(now time.Time, path string, authKey string) string {
timestamp := strconv.FormatInt(now.Add(2*time.Hour).Unix(), 16)
base64 := path
signStr := authKey + base64 + timestamp
md5Str := getMD5Sign(signStr)
urlAuth := fmt.Sprintf("?sign=%s&t=%s", md5Str, timestamp)
return urlAuth
}
// getMD5Sign 得到签名
func getMD5Sign(buf string) string {
md5Ctx := md5.New()
md5Ctx.Write([]byte(buf))
cipherStr := md5Ctx.Sum(nil)
nsign := hex.EncodeToString(cipherStr)
return nsign
}