package m3u8 import ( "bytes" "fmt" "strings" "videoweb/pub/common/errors" "videoweb/pub/common/utils" "videoweb/pub/storage/proxy" "github.com/grafov/m3u8" ) const lsjKeyIV = "0x64cf692cebc516e4a86ac6081aae50ce" // TransformForTranscode 生成转码专用播放列表,供老司机转码服务器拉取。 func TransformForTranscode(name, origDomain, cdnDomain, webM3u8Host, lsjM3u8Yuan, lsjTsYuan string) (media *m3u8.MediaPlaylist, buff *bytes.Buffer, err error) { if strings.Contains(name, "hc237") { name = "/laosiji" + name } if strings.Contains(name, "laosiji") { return transcodeLaosiji(name, webM3u8Host, lsjM3u8Yuan, lsjTsYuan) } return transcodeNormal(name, origDomain, cdnDomain, webM3u8Host) } func transcodeLaosiji(name, webM3u8Host, lsjM3u8Yuan, lsjTsYuan string) (media *m3u8.MediaPlaylist, buff *bytes.Buffer, err error) { m3u8reader, err := readFromRedis(laosijiUpstreamPath(name), lsjM3u8Yuan) if err != nil { return } p, t, err := m3u8.DecodeFrom(m3u8reader, false) if err != nil { err = errors.MakeWithErr(errors.M3u8Read, err) return } switch t { case m3u8.MEDIA: pl := p.(*m3u8.MediaPlaylist) keyURI := utils.JoinUrlPath(webM3u8Host, keyUriWebLsj) // ts 走 CDN(TsYuan/laosiji),与正常播放的 CDN 路径一致。 media, err = makeTranscodeSegList(pl, utils.JoinUrlPath(lsjTsYuan, "/laosiji"), "", keyURI, lsjKeyIV, true) if err != nil { return } buff = media.Encode() case m3u8.MASTER: buff = p.(*m3u8.MasterPlaylist).Encode() default: err = errors.MakeWithMsg(errors.M3u8FileName, fmt.Sprintf("invalid m3u8 type %d", t)) } return } func transcodeNormal(name, origDomain, cdnDomain, webM3u8Host string) (media *m3u8.MediaPlaylist, buff *bytes.Buffer, err error) { if v := proxy.AppendsMediaS3Version(name); len(v) > 0 { name = v + name } 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 } switch t { case m3u8.MEDIA: pl := p.(*m3u8.MediaPlaylist) dirPath := utils.PathForInfo(name).Dir keyURI := utils.JoinUrlPath(webM3u8Host, webkeyUri) // ts 走 CDN(CdnDomain),与正常播放一致。 media, err = makeTranscodeSegList(pl, cdnDomain, dirPath, keyURI, "", false) if err != nil { return } buff = media.Encode() case m3u8.MASTER: buff = p.(*m3u8.MasterPlaylist).Encode() default: err = errors.MakeWithMsg(errors.M3u8FileName, fmt.Sprintf("invalid m3u8 type %d", t)) } return } func makeTranscodeSegList(from *m3u8.MediaPlaylist, srcDomain, dirPath, keyURI, iv string, laosiji bool) (media *m3u8.MediaPlaylist, err error) { media, err = m3u8.NewMediaPlaylist(0, from.Count()) if err != nil { return } base := utils.JoinUrlPath(srcDomain, dirPath) for _, segment := range from.Segments { if segment == nil { continue } sg := new(m3u8.MediaSegment) if laosiji { if u, e := replaceDomainAndPath(segment.URI, srcDomain); e == nil { sg.URI = u } else { sg.URI = segment.URI } } else { sg.URI = utils.JoinUrlPath(base, segment.URI) } sg.Title = segment.Title sg.Duration = segment.Duration if err = media.AppendSegment(sg); err != nil { return } } _ = media.SetDefaultKey("AES-128", keyURI, iv, "", "") media.Close() return }