160 lines
4.6 KiB
Go
160 lines
4.6 KiB
Go
package video
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
dto "media/model/dto/video"
|
|
entity "media/model/entity/video"
|
|
|
|
"gitea.redpowerfuture.com/red-future/common/db/gfdb"
|
|
"github.com/gogf/gf/v2/frame/g"
|
|
"github.com/gogf/gf/v2/util/gconv"
|
|
)
|
|
|
|
var SceneSplitTask = new(sceneSplitTaskDao)
|
|
|
|
type sceneSplitTaskDao struct{}
|
|
|
|
const sceneSplitTaskTable = "scene_split_task"
|
|
|
|
// Insert 创建任务(排除 id 字段,让数据库自增)
|
|
func (d *sceneSplitTaskDao) Insert(ctx context.Context, data *entity.SceneSplitTask) (id int64, err error) {
|
|
r, err := gfdb.DB(ctx).Model(ctx, sceneSplitTaskTable).
|
|
Data(data).
|
|
FieldsEx(entity.SceneSplitTaskCols.Id).
|
|
Insert()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return r.LastInsertId()
|
|
}
|
|
|
|
// GetByTaskID 根据taskId查询任务
|
|
func (d *sceneSplitTaskDao) GetByTaskID(ctx context.Context, taskID string) (res *entity.SceneSplitTask, err error) {
|
|
r, err := gfdb.DB(ctx).Model(ctx, sceneSplitTaskTable).
|
|
Where(entity.SceneSplitTaskCols.TaskID, taskID).
|
|
One()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if r == nil {
|
|
return nil, nil
|
|
}
|
|
err = r.Struct(&res)
|
|
return
|
|
}
|
|
|
|
// UpdateRunning 更新为运行中
|
|
func (d *sceneSplitTaskDao) UpdateRunning(ctx context.Context, taskID string) error {
|
|
_, err := gfdb.DB(ctx).Model(ctx, sceneSplitTaskTable).
|
|
Data(g.Map{
|
|
entity.SceneSplitTaskCols.Status: "running",
|
|
}).
|
|
Where(entity.SceneSplitTaskCols.TaskID, taskID).
|
|
Update()
|
|
return err
|
|
}
|
|
|
|
// UpdateSuccess 更新为成功
|
|
func (d *sceneSplitTaskDao) UpdateSuccess(ctx context.Context, taskID string, segmentURLs, audioURL string, sceneCount int, audioDuration float64, videoDuration float64) error {
|
|
_, err := gfdb.DB(ctx).Model(ctx, sceneSplitTaskTable).
|
|
Data(g.Map{
|
|
entity.SceneSplitTaskCols.Status: "success",
|
|
entity.SceneSplitTaskCols.SegmentURLs: segmentURLs,
|
|
entity.SceneSplitTaskCols.AudioURL: audioURL,
|
|
entity.SceneSplitTaskCols.SceneCount: sceneCount,
|
|
entity.SceneSplitTaskCols.AudioDuration: audioDuration,
|
|
entity.SceneSplitTaskCols.VideoDuration: videoDuration,
|
|
entity.SceneSplitTaskCols.ErrorMessage: "",
|
|
}).
|
|
Where(entity.SceneSplitTaskCols.TaskID, taskID).
|
|
Update()
|
|
return err
|
|
}
|
|
|
|
// UpdateError 更新为失败
|
|
func (d *sceneSplitTaskDao) UpdateError(ctx context.Context, taskID string, errMsg string) error {
|
|
_, err := gfdb.DB(ctx).Model(ctx, sceneSplitTaskTable).
|
|
Data(g.Map{
|
|
entity.SceneSplitTaskCols.Status: "failed",
|
|
entity.SceneSplitTaskCols.ErrorMessage: errMsg,
|
|
}).
|
|
Where(entity.SceneSplitTaskCols.TaskID, taskID).
|
|
Update()
|
|
return err
|
|
}
|
|
|
|
// EntityToSceneSplitTaskRes 实体转DTO
|
|
func EntityToSceneSplitTaskRes(e *entity.SceneSplitTask) *dto.GetSceneSplitTaskRes {
|
|
res := &dto.GetSceneSplitTaskRes{
|
|
TaskID: e.TaskID,
|
|
Status: e.Status,
|
|
SceneCount: e.SceneCount,
|
|
AudioDuration: e.AudioDuration,
|
|
VideoDuration: e.VideoDuration,
|
|
}
|
|
if e.CreatedAt != nil {
|
|
res.CreatedAt = gconv.Int64(e.CreatedAt.Timestamp())
|
|
} else {
|
|
res.CreatedAt = time.Now().UnixMilli()
|
|
}
|
|
if e.Status == "success" {
|
|
res.AudioURL = e.AudioURL
|
|
res.Segments = ParseSegmentEntries(e.SegmentURLs)
|
|
res.SceneCount = e.SceneCount
|
|
res.AudioDuration = e.AudioDuration
|
|
res.VideoDuration = e.VideoDuration
|
|
}
|
|
if e.Status == "failed" {
|
|
res.ErrorMessage = e.ErrorMessage
|
|
}
|
|
return res
|
|
}
|
|
|
|
// ParseSegmentEntries 将 JSON 数组解析为按时间线排序的 SegmentEntry 切片
|
|
// JSON 格式: [{"timeline":"0.0-7.2","url":"..."}, ...]
|
|
func ParseSegmentEntries(jsonStr string) []dto.SegmentEntry {
|
|
if jsonStr == "" {
|
|
return nil
|
|
}
|
|
|
|
// 先尝试解析为数组格式
|
|
var entries []dto.SegmentEntry
|
|
if err := json.Unmarshal([]byte(jsonStr), &entries); err == nil && len(entries) > 0 {
|
|
// 按起始时间排序确保有序
|
|
sort.Slice(entries, func(i, j int) bool {
|
|
return extractStartTime(entries[i].Timeline) < extractStartTime(entries[j].Timeline)
|
|
})
|
|
return entries
|
|
}
|
|
|
|
// 兼容旧的 map 格式 {"0.0-7.2":"url", ...}
|
|
var m map[string]string
|
|
if err := json.Unmarshal([]byte(jsonStr), &m); err != nil {
|
|
return nil
|
|
}
|
|
entries = make([]dto.SegmentEntry, 0, len(m))
|
|
for timeline, url := range m {
|
|
entries = append(entries, dto.SegmentEntry{Timeline: timeline, URL: url})
|
|
}
|
|
sort.Slice(entries, func(i, j int) bool {
|
|
return extractStartTime(entries[i].Timeline) < extractStartTime(entries[j].Timeline)
|
|
})
|
|
return entries
|
|
}
|
|
|
|
// extractStartTime 从时间线 key(如 "0.0-7.2")提取起始秒数用于排序
|
|
func extractStartTime(timeline string) float64 {
|
|
idx := strings.Index(timeline, "-")
|
|
if idx < 0 {
|
|
return 0
|
|
}
|
|
v, _ := strconv.ParseFloat(timeline[:idx], 64)
|
|
return v
|
|
}
|