Files
web_huakui_server/pub/common/m3u8/transcode_source.go
T
rootandClaude Opus 4.7 85c0071fd8 feat: 从黄果 NET hgdjnet-server 9bfbafe 导入 HKDJ 官网后端
来源:hgdjnet-server 9bfbafe10d417deea959bd53117bc88a10e60a83
项目身份 HKDJ / JHA-216,独立官网仓库,Jenkins 守卫键 hkdjnet
测试目录 /server/hkdj_net,App/Web API 30331/30332

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-10-16 11:20:04 +08:00

117 lines
3.3 KiB
Go
Raw 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"
"fmt"
"hkdj-web-server/pub/common/errors"
"hkdj-web-server/pub/common/utils"
"hkdj-web-server/pub/storage/proxy"
"strings"
"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
}