init: 初始化 web_hgdjb_server 项目
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
package srv_videoinfo
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"videoweb/pub/common/laosiji"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/srvdef"
|
||||
"videoweb/pub/common/utils"
|
||||
"videoweb/pub/models/videoinformationmod"
|
||||
"videoweb/web/webg"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
)
|
||||
|
||||
// TranscodeVideo 手动提交主视频 H265 转码。
|
||||
func TranscodeVideo(ctx context.Context, videoId int64) *srvdef.SrvErr {
|
||||
info, serr := videoinformationmod.FindOneVideoInformation(ctx, bson.M{
|
||||
videoinformationmod.FN.VideoInformation.Id: videoId,
|
||||
})
|
||||
if serr != nil {
|
||||
return serr
|
||||
}
|
||||
src := strings.TrimSpace(info.Video.Url)
|
||||
if src == "" {
|
||||
return srvdef.New(srvdef.Err, "", "该视频没有可转码的源地址")
|
||||
}
|
||||
if laosiji.LaosijiClient == nil || laosiji.LaosijiDomains == nil {
|
||||
return srvdef.New(srvdef.Err, "", "转码服务未就绪")
|
||||
}
|
||||
if info.HevcStatus == videoinformationmod.HevcStatusPending {
|
||||
return srvdef.New(srvdef.Err, "", "转码请求已提交,正在转码中,请勿重复提交")
|
||||
}
|
||||
if err := SubmitTranscodeVideo(ctx, videoId, src, info.Video.FileId); err != nil {
|
||||
return srvdef.New(srvdef.Err, "", "提交转码失败:"+err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildTranscodeSourceURL(videoUrl string) string {
|
||||
name := strings.TrimSpace(videoUrl)
|
||||
if name == "" {
|
||||
return ""
|
||||
}
|
||||
if !strings.Contains(name, ".m3u8") {
|
||||
name += ".m3u8"
|
||||
}
|
||||
host := strings.TrimSpace(webg.Conf.WebM3u8Host)
|
||||
if host == "" {
|
||||
return ""
|
||||
}
|
||||
return utils.JoinUrlPath(host, "/api/web/m3u8/"+name)
|
||||
}
|
||||
|
||||
// SubmitTranscodeVideo 提交主视频转码任务。
|
||||
func SubmitTranscodeVideo(ctx context.Context, videoId int64, src, fileId string) error {
|
||||
fileURL := buildTranscodeSourceURL(src)
|
||||
if fileURL == "" {
|
||||
return fmt.Errorf("empty transcode source url, videoUrl:%s host:%s", src, webg.Conf.WebM3u8Host)
|
||||
}
|
||||
sd, err := laosiji.LaosijiDomains.Get(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := laosiji.LaosijiClient.SubmitTranscoding(ctx, fileURL, fileId, *sd, videoId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return applyTranscodeResult(ctx, videoId, result)
|
||||
}
|
||||
|
||||
// RefreshTranscodeVideo 查询转码任务状态并回写。
|
||||
func RefreshTranscodeVideo(ctx context.Context, videoId int64, src, fileId string) error {
|
||||
fileURL := buildTranscodeSourceURL(src)
|
||||
if fileURL == "" {
|
||||
return fmt.Errorf("empty transcode source url, videoUrl:%s host:%s", src, webg.Conf.WebM3u8Host)
|
||||
}
|
||||
sd, err := laosiji.LaosijiDomains.Get(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, found, err := laosiji.LaosijiClient.QueryTranscoding(ctx, fileURL, fileId, *sd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !found {
|
||||
return nil
|
||||
}
|
||||
return applyTranscodeResult(ctx, videoId, result)
|
||||
}
|
||||
|
||||
func applyTranscodeResult(ctx context.Context, videoId int64, result laosiji.TranscodeResult) error {
|
||||
log.Infof("==applyTranscodeResult===> result", log.Any("videoId", videoId), log.Any("result", result))
|
||||
var update bson.M
|
||||
switch {
|
||||
case result.Done:
|
||||
meta := toVideoMetaInfo(result.HevcMeta)
|
||||
if meta == nil {
|
||||
meta = &videoinformationmod.VideoMetaInfo{}
|
||||
}
|
||||
h265Url := normalizeH265UrlForSave(result.HevcURL)
|
||||
meta.M3u8URL = h265Url
|
||||
set := bson.M{
|
||||
videoinformationmod.FN.VideoInformation.HevcStatus: videoinformationmod.HevcStatusSuccess,
|
||||
videoinformationmod.FN.VideoInformation.HevcMetaInfo: meta,
|
||||
videoinformationmod.FN.VideoInformation.Video.H265Url: h265Url,
|
||||
}
|
||||
if result.PreviewVtt != "" {
|
||||
set[videoinformationmod.FN.VideoInformation.PreviewVtt] = result.PreviewVtt
|
||||
}
|
||||
if result.AudioFile != "" {
|
||||
set[videoinformationmod.FN.VideoInformation.AudioFile] = result.AudioFile
|
||||
}
|
||||
if result.SmartCover != "" {
|
||||
set[videoinformationmod.FN.VideoInformation.SmartCover] = result.SmartCover
|
||||
}
|
||||
update = bson.M{"$set": set}
|
||||
case result.Failed:
|
||||
update = bson.M{
|
||||
"$set": bson.M{videoinformationmod.FN.VideoInformation.HevcStatus: videoinformationmod.HevcStatusFailed},
|
||||
"$inc": bson.M{videoinformationmod.FN.VideoInformation.HevcFailCount: 1},
|
||||
}
|
||||
default:
|
||||
update = bson.M{"$set": bson.M{videoinformationmod.FN.VideoInformation.HevcStatus: videoinformationmod.HevcStatusPending}}
|
||||
}
|
||||
if serr := videoinformationmod.UpdateOneVideoInformation(ctx, bson.M{
|
||||
videoinformationmod.FN.VideoInformation.Id: videoId,
|
||||
}, update); serr != nil {
|
||||
return fmt.Errorf("update video transcode status: %v", serr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func normalizeH265UrlForSave(url string) string {
|
||||
url = strings.TrimSpace(url)
|
||||
return strings.TrimPrefix(url, "/")
|
||||
}
|
||||
|
||||
func toVideoMetaInfo(m *laosiji.MetaInfo) *videoinformationmod.VideoMetaInfo {
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
return &videoinformationmod.VideoMetaInfo{
|
||||
Codec: m.Codec,
|
||||
Profile: m.Profile,
|
||||
Width: m.Width,
|
||||
Height: m.Height,
|
||||
Fps: m.Fps,
|
||||
VideoBitrate: m.VideoBitrate,
|
||||
PixFmt: m.PixFmt,
|
||||
AudioCodec: m.AudioCodec,
|
||||
AudioBitrate: m.AudioBitrate,
|
||||
AudioSampleRate: m.AudioSampleRate,
|
||||
AudioChannels: m.AudioChannels,
|
||||
Bitrate: m.Bitrate,
|
||||
Size: m.Size,
|
||||
Duration: m.Duration,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user