Files
rootandClaude Opus 5.5 7974a42301 Initial commit
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-23 11:07:42 +08:00

212 lines
7.3 KiB
Go

package srv_videoinfo
import (
"context"
"strings"
"time"
"videoweb/pub/common/log"
"videoweb/pub/common/srvdef"
"videoweb/pub/models/videocreatermod"
"videoweb/pub/models/videoinformationmod"
"videoweb/pub/mongos"
"videoweb/pub/storage/proxy"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo/options"
)
func SyncOneVideo(ctx context.Context, media proxy.MediaResp) *srvdef.SrvErr {
filter := bson.M{
"$or": []bson.M{
{videoinformationmod.FN.VideoInformation.Video.FileId: media.Id.Hex()},
{videoinformationmod.FN.VideoInformation.SyncId: media.Id.Hex()},
},
}
videoInfo, serr := videoinformationmod.FindOneVideoInformation(ctx, filter)
if serr != nil {
// 新加入的视频
if serr.Code == srvdef.ErrNoData {
videoInfo = media.ToVideoInfo()
if videoInfo == nil {
log.Error("VideoSync FindOneVideoInformation", log.Any("MediaId", media.Id))
return srvdef.New(srvdef.ErrNoData, "videoInfo is nil")
}
videoInfo.IndexNow = 0
if len(media.Publish) > 0 {
creater, serr := videocreatermod.FindOneVideoCreaterInfo(ctx, bson.M{
videocreatermod.FN.VideoCreaterInfo.Name: media.Publish,
})
if serr != nil && serr.Code != srvdef.ErrNoData {
log.Error("VideoSync.FindOneVideoCreaterInfo", log.Any("media", media), log.E(serr))
return serr
}
if creater == nil {
createrId := mongos.Lid.VideoCreator.Get()
creater = &videocreatermod.VideoCreaterInfo{
Id: createrId,
Name: media.Publish,
Status: true,
Sort: 0,
UpdatedAt: time.Now(),
CreatedAt: time.Now(),
}
serr = videocreatermod.InsertOneVideoCreaterInfo(ctx, creater)
if serr != nil {
log.Error("VideoSync.InsertOneVideoCreaterInfo", log.Any("media", media), log.E(serr))
return serr
}
}
videoInfo.CreatorId = creater.Id
videoInfo.CreatorName = creater.Name
}
serr = videoinformationmod.InsertOneVideoInformation(ctx, videoInfo)
if serr != nil {
log.Error("VideoSync InsertOneVideoInformation", log.Any("videoInfo", videoInfo), log.E(serr))
return serr
}
} else {
log.Error("VideoSync FindOneVideoInformation", log.Any("filter", filter), log.E(serr))
return serr
}
} else {
// 更新资源
nodes := make([]videoinformationmod.Node, 0)
if videoInfo != nil {
// 更新节点里面图片水印 以本地视频列表的节点为主
for _, node := range videoInfo.Nodes {
isFind := false
if len(node.NodeId) > 0 {
for _, v := range media.Nodes {
if node.NodeId == v.NodeId {
isFind = true
node.Images = v.Images
nodes = append(nodes, node)
break
}
}
}
if !isFind {
nodes = append(nodes, node)
}
}
} else {
nodes = media.Nodes
}
setDoc := bson.M{
videoinformationmod.FN.VideoInformation.Nodes: nodes,
videoinformationmod.FN.VideoInformation.Keyworld: media.Keyworld,
videoinformationmod.FN.VideoInformation.FirstTag: media.FirstTag,
videoinformationmod.FN.VideoInformation.SecondTags: media.SecondTags,
videoinformationmod.FN.VideoInformation.CoverImg: media.CoverImg,
videoinformationmod.FN.VideoInformation.UnencryptedImage: media.UnencryptedImage,
}
if len(media.FieldNameFs) > 0 {
video := videoinformationmod.VideoInfo{
TaskId: media.TaskID,
FileId: media.Id.Hex(),
Url: media.FieldNameFs,
Cover: media.CoverImg,
Height: media.Height,
Width: media.Width,
VideoTime: media.VideoTime,
UnencryptedPreMp4: media.UnencryptedPreMp4,
PreMp4FileNameFs: media.PreMp4FileNameFs,
}
if !strings.HasSuffix(video.Url, ".m3u8") {
video.Url += ".m3u8"
}
setDoc[videoinformationmod.FN.VideoInformation.Video.TaskId] = video.TaskId
setDoc[videoinformationmod.FN.VideoInformation.Video.FileId] = video.FileId
setDoc[videoinformationmod.FN.VideoInformation.Video.Url] = video.Url
setDoc[videoinformationmod.FN.VideoInformation.Video.Cover] = video.Cover
setDoc[videoinformationmod.FN.VideoInformation.Video.Height] = video.Height
setDoc[videoinformationmod.FN.VideoInformation.Video.Width] = video.Width
setDoc[videoinformationmod.FN.VideoInformation.Video.VideoTime] = video.VideoTime
setDoc[videoinformationmod.FN.VideoInformation.Video.UnencryptedPreMp4] = video.UnencryptedPreMp4
}
serr = videoinformationmod.UpdateOneVideoInformation(ctx, bson.M{videoinformationmod.FN.VideoInformation.Id: videoInfo.Id}, bson.M{"$set": setDoc})
if serr != nil {
return serr
}
}
_ = syncNodeVideo(ctx, media)
return nil
}
// SyncUnencryptedOne 仅补齐单条资源的 UnencryptedImage / UnencryptedPreMp4 字段。
// 源数据对应字段为空时跳过该字段(避免覆盖本地已有值);本地无对应资源时直接返回。
// 幂等:可重复执行,用于历史数据补齐。
func SyncUnencryptedOne(ctx context.Context, media proxy.MediaResp) *srvdef.SrvErr {
if media.UnencryptedImage == "" && media.UnencryptedPreMp4 == "" {
return nil
}
filter := bson.M{videoinformationmod.FN.VideoInformation.Video.FileId: media.Id.Hex()}
videoInfo, serr := videoinformationmod.FindOneVideoInformation(ctx, filter)
if serr != nil {
return serr
}
setDoc := bson.M{}
if media.UnencryptedImage != "" {
setDoc[videoinformationmod.FN.VideoInformation.UnencryptedImage] = media.UnencryptedImage
}
// 仅当源端有主视频文件时,才补 Video.UnencryptedPreMp4(避免向空的 Video 子结构写字段)
if media.UnencryptedPreMp4 != "" && len(media.FieldNameFs) > 0 {
setDoc[videoinformationmod.FN.VideoInformation.Video.UnencryptedPreMp4] = media.UnencryptedPreMp4
}
if len(setDoc) == 0 {
return nil
}
return videoinformationmod.UpdateOneVideoInformation(ctx,
bson.M{videoinformationmod.FN.VideoInformation.Id: videoInfo.Id},
bson.M{"$set": setDoc})
}
// syncNodeVideo 同步节点里的视频
func syncNodeVideo(ctx context.Context, media proxy.MediaResp) *srvdef.SrvErr {
filter := bson.M{"nodes.nodeId": media.Id.Hex()}
opts := &options.FindOptions{}
opts.SetLimit(100)
videoInfo, serr := videoinformationmod.FindManyVideoInformations(ctx, filter, opts)
if serr != nil {
log.Warn("syncNodeVideo", log.Any("filter", filter), log.E(serr))
return serr
}
if !strings.HasSuffix(media.FieldNameFs, ".m3u8") {
media.FieldNameFs += ".m3u8"
}
if len(videoInfo) > 0 {
// 更新视频路径
for _, video := range videoInfo {
if video.Nodes != nil && len(video.Nodes) > 0 {
isFind := false
for i, node := range video.Nodes {
if node.Videos != nil && len(node.Videos) > 0 {
for j, v := range node.Videos {
if v.FileId == media.Id.Hex() {
node.Videos[j].Url = media.FieldNameFs
isFind = true
break
}
}
}
if isFind {
video.Nodes[i] = node
break
}
}
if isFind {
serr = videoinformationmod.UpdateOneVideoInformation(ctx, bson.M{videoinformationmod.FN.VideoInformation.Id: video.Id}, bson.M{"$set": bson.M{
videoinformationmod.FN.VideoInformation.UpdatedAt: time.Now(),
videoinformationmod.FN.VideoInformation.Nodes: video.Nodes,
}})
if serr != nil {
log.Warn("syncNodeVideo UpdateOneVideoInformation failed", log.Any("filter", filter), log.E(serr))
continue
}
}
}
}
}
return nil
}