视频剪辑和处理
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
package video
|
||||
|
||||
import "github.com/gogf/gf/v2/frame/g"
|
||||
|
||||
// ---------- 场景检测+视频分割(异步)----------
|
||||
|
||||
// SceneSplitReq 场景检测+视频分割请求
|
||||
type SceneSplitReq struct {
|
||||
g.Meta `path:"/scene-split" method:"post" tags:"场景分割" summary:"场景检测并分割视频(异步)" dc:"下载视频,基于PySceneDetect检测场景变化并分割成多个视频片段,同时提取音频,全部上传到MinIO后回调通知"`
|
||||
VideoURL string `json:"videoUrl" v:"required#视频URL不能为空" dc:"视频URL地址"`
|
||||
Threshold float64 `json:"threshold" dc:"场景检测阈值(默认27),越小越敏感、场景切割越多" d:"27.0"`
|
||||
CallbackURL string `json:"callbackUrl" dc:"回调地址,处理完成后POST结果到该地址(可选)"`
|
||||
}
|
||||
|
||||
// CreateSceneSplitTaskRes 创建场景分割任务响应
|
||||
type CreateSceneSplitTaskRes struct {
|
||||
TaskID string `json:"taskId" dc:"任务ID"`
|
||||
}
|
||||
|
||||
// GetSceneSplitTaskReq 查询场景分割任务请求
|
||||
type GetSceneSplitTaskReq struct {
|
||||
g.Meta `path:"/scene-split/task/{taskId}" method:"get" tags:"场景分割" summary:"查询场景分割任务结果" dc:"根据taskId查询异步场景分割任务结果"`
|
||||
TaskID string `json:"taskId" dc:"任务ID"`
|
||||
}
|
||||
|
||||
// SegmentEntry 单个分片信息(按时间线排列)
|
||||
type SegmentEntry struct {
|
||||
Timeline string `json:"timeline" dc:"时间线标识,如 0.0-7.2"`
|
||||
URL string `json:"url" dc:"分片MinIO地址"`
|
||||
}
|
||||
|
||||
// GetSceneSplitTaskRes 查询场景分割任务响应
|
||||
type GetSceneSplitTaskRes struct {
|
||||
TaskID string `json:"taskId" dc:"任务ID"`
|
||||
Status string `json:"status" dc:"状态: pending/running/success/failed"`
|
||||
AudioURL string `json:"audioUrl,omitempty" dc:"提取的音频MinIO地址"`
|
||||
Segments []SegmentEntry `json:"segments,omitempty" dc:"按时间线排列的视频分片列表"`
|
||||
SceneCount int `json:"sceneCount" dc:"检测到的场景数/分片数"`
|
||||
AudioDuration float64 `json:"audioDuration,omitempty" dc:"音频时长(秒)"`
|
||||
VideoDuration float64 `json:"videoDuration,omitempty" dc:"视频总时长(秒)"`
|
||||
ErrorMessage string `json:"errorMessage,omitempty" dc:"错误信息"`
|
||||
CreatedAt int64 `json:"createdAt" dc:"创建时间戳"`
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package video
|
||||
|
||||
// TranscodeRes 视频转码响应
|
||||
type TranscodeRes struct {
|
||||
OutputPath string `json:"outputPath" dc:"输出文件完整路径"`
|
||||
FileSize int64 `json:"fileSize" dc:"文件大小(字节)"`
|
||||
FileName string `json:"fileName" dc:"输出文件名"`
|
||||
DurationStr string `json:"durationStr" dc:"视频时长"`
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package video
|
||||
|
||||
import "github.com/gogf/gf/v2/frame/g"
|
||||
|
||||
// ---------- 视频拼接+混音(异步) ----------
|
||||
|
||||
// VideoAudioMergeAsyncReq 视频拼接+混音异步请求
|
||||
type VideoAudioMergeAsyncReq struct {
|
||||
g.Meta `path:"/merge/async" method:"post" tags:"视频拼接+混音" summary:"视频拼接并混音(异步)" dc:"将多个视频拼接后混入多个音频(按顺序拼接),立即返回taskId,完成后通过callback_url通知结果"`
|
||||
VideoURLs []string `json:"video_urls" v:"required#视频URL列表不能为空" dc:"视频URL列表(按此顺序拼接)"`
|
||||
AudioURLs []string `json:"audio_urls" v:"required#音频URL列表不能为空" dc:"音频URL列表(按此顺序拼接)"`
|
||||
Upload bool `json:"upload" dc:"是否上传到MinIO" d:"false"`
|
||||
CallbackURL string `json:"callback_url" v:"required#回调地址不能为空" dc:"回调地址,处理完成后POST结果到该地址"`
|
||||
}
|
||||
|
||||
// CreateMergeTaskRes 创建异步拼接+混音任务响应
|
||||
type CreateMergeTaskRes struct {
|
||||
TaskID string `json:"taskId" dc:"任务ID"`
|
||||
}
|
||||
|
||||
// GetMergeTaskReq 查询异步拼接+混音任务请求
|
||||
type GetMergeTaskReq struct {
|
||||
g.Meta `path:"/merge/task/{taskId}" method:"get" tags:"视频拼接+混音" summary:"查询拼接混音任务结果" dc:"根据taskId查询异步拼接+混音任务的结果"`
|
||||
TaskID string `json:"taskId" dc:"任务ID"`
|
||||
}
|
||||
|
||||
// GetMergeTaskRes 查询异步拼接+混音任务响应
|
||||
type GetMergeTaskRes struct {
|
||||
TaskID string `json:"taskId" dc:"任务ID"`
|
||||
Status string `json:"status" dc:"状态: pending/running/success/failed"`
|
||||
FileURL string `json:"fileURL,omitempty" dc:"MinIO文件访问路径"`
|
||||
FileSize int64 `json:"fileSize,omitempty" dc:"文件大小(字节)"`
|
||||
FileName string `json:"fileName,omitempty" dc:"文件名"`
|
||||
FileFormat string `json:"fileFormat,omitempty" dc:"文件格式"`
|
||||
FileAddressPrefix string `json:"fileAddressPrefix,omitempty" dc:"MinIO地址前缀"`
|
||||
DurationStr string `json:"durationStr,omitempty" dc:"合并后视频时长"`
|
||||
ErrorMessage string `json:"errorMessage,omitempty" dc:"错误信息"`
|
||||
CreatedAt int64 `json:"createdAt" dc:"创建时间戳"`
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package video
|
||||
|
||||
import "github.com/gogf/gf/v2/frame/g"
|
||||
|
||||
// ---------- 字幕元素定义 ----------
|
||||
|
||||
// CaptionElement 单个字幕/图片元素
|
||||
type CaptionElement struct {
|
||||
Type string `json:"type" v:"required#元素类型必填" dc:"元素类型:text/image"`
|
||||
Text string `json:"text" dc:"文字内容(type=text时必填)"`
|
||||
ImageURL string `json:"imageUrl" dc:"图片URL(type=image时必填)"`
|
||||
StartTime float64 `json:"startTime" d:"0" dc:"开始时间(秒,默认0)"`
|
||||
Duration float64 `json:"duration" d:"0" dc:"持续时长(秒,0或空=一直显示到视频结束)"`
|
||||
X string `json:"x" d:"center" dc:"水平位置:left/center/right或像素值"`
|
||||
Y string `json:"y" d:"center" dc:"垂直位置:top/center/bottom或像素值"`
|
||||
FontSize int `json:"fontSize" d:"36" dc:"字号(type=text有效)"`
|
||||
FontColor string `json:"fontColor" d:"#FFFFFF" dc:"字体颜色"`
|
||||
BgColor string `json:"bgColor" dc:"背景色,如#FFFF00,空=透明"`
|
||||
BgOpacity float64 `json:"bgOpacity" d:"1.0" dc:"背景透明度0-1"`
|
||||
Width int `json:"width" dc:"元素宽度(type=image有效)"`
|
||||
Height int `json:"height" dc:"元素高度(type=image有效)"`
|
||||
Animation string `json:"animation" dc:"动画效果:fadeIn/slideUp/slideLeft/scaleIn"`
|
||||
TrackIndex int `json:"trackIndex" d:"1" dc:"轨道层级(数字越大越靠前)"`
|
||||
}
|
||||
|
||||
// SubtitleSegment 外部传入的字幕时间线片段
|
||||
type SubtitleSegment struct {
|
||||
Start float64 `json:"start" v:"required#开始时间必填" dc:"开始时间(秒)"`
|
||||
End float64 `json:"end" v:"required#结束时间必填" dc:"结束时间(秒)"`
|
||||
Text string `json:"text" v:"required#字幕文本必填" dc:"字幕文本内容"`
|
||||
}
|
||||
|
||||
// SubtitleStyle 字幕样式配置
|
||||
type SubtitleStyle struct {
|
||||
FontSize int `json:"fontSize" d:"28" dc:"字号(默认28)"`
|
||||
FontColor string `json:"fontColor" d:"#FFFFFF" dc:"字体颜色(默认白色)"`
|
||||
BgColor *string `json:"bgColor" dc:"背景色,空字符串=透明(默认#000000)。传空字符串 '' 可去掉背景色"`
|
||||
BgOpacity *float64 `json:"bgOpacity" dc:"背景透明度0-1(默认0.6)。传0可使背景完全透明"`
|
||||
X string `json:"x" d:"center" dc:"水平位置:left/center/right或像素值(默认center)"`
|
||||
Y string `json:"y" d:"bottom" dc:"垂直位置:top/center/bottom或像素值(默认bottom)"`
|
||||
}
|
||||
|
||||
// ---------- 创建字幕任务 ----------
|
||||
|
||||
// CreateCaptionTaskReq 创建字幕叠加任务请求
|
||||
type CreateCaptionTaskReq struct {
|
||||
g.Meta `path:"/" method:"post" tags:"字幕叠加" summary:"创建字幕叠加任务(异步)" dc:"创建使用HyperFrames渲染的视频字幕叠加任务,返回taskId"`
|
||||
VideoURLs []string `json:"video_urls" v:"required#视频URL列表不能为空" dc:"背景视频URL列表"`
|
||||
AudioURL string `json:"audio_url" dc:"背景音频URL(可选)"`
|
||||
Subtitles []SubtitleSegment `json:"subtitles" dc:"字幕时间线列表(可选),每段包含起始时间和文本"`
|
||||
SubtitleStyle *SubtitleStyle `json:"subtitle_style" dc:"字幕样式配置(可选),不传则使用默认值"`
|
||||
Elements []CaptionElement `json:"elements" dc:"字幕/图片元素列表(可选)"`
|
||||
CallbackURL string `json:"callback_url" dc:"任务完成后的回调地址(可选)"`
|
||||
}
|
||||
|
||||
// CreateCaptionTaskRes 创建字幕任务响应
|
||||
type CreateCaptionTaskRes struct {
|
||||
TaskID string `json:"taskId" dc:"任务ID"`
|
||||
}
|
||||
|
||||
// ---------- 查询字幕任务 ----------
|
||||
|
||||
// GetCaptionTaskReq 查询字幕任务请求
|
||||
type GetCaptionTaskReq struct {
|
||||
g.Meta `path:"/{taskId}" method:"get" tags:"字幕叠加" summary:"查询字幕任务结果" dc:"根据taskId查询字幕任务详情"`
|
||||
TaskID string `json:"taskId" dc:"任务ID"`
|
||||
}
|
||||
|
||||
// GetCaptionTaskRes 查询字幕任务响应
|
||||
type GetCaptionTaskRes struct {
|
||||
TaskID string `json:"taskId" dc:"任务ID"`
|
||||
Status string `json:"status" dc:"任务状态"`
|
||||
FileURL string `json:"fileUrl,omitempty" dc:"输出文件URL"`
|
||||
FileSize int64 `json:"fileSize,omitempty" dc:"输出文件大小"`
|
||||
FileName string `json:"fileName,omitempty" dc:"输出文件名"`
|
||||
DurationStr string `json:"durationStr,omitempty" dc:"视频时长"`
|
||||
ErrorMessage string `json:"errorMessage,omitempty" dc:"错误信息"`
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package video
|
||||
|
||||
import "gitea.redpowerfuture.com/red-future/common/beans"
|
||||
|
||||
// SceneSplitTask 场景检测+视频分割异步任务实体
|
||||
type SceneSplitTask struct {
|
||||
beans.SQLBaseDO `orm:",inherit"`
|
||||
TaskID string `orm:"task_id" json:"taskId" description:"任务唯一标识"`
|
||||
VideoURL string `orm:"video_url" json:"videoUrl" description:"原始视频URL"`
|
||||
Status string `orm:"status" json:"status" description:"任务状态:pending/running/success/failed"`
|
||||
SegmentURLs string `orm:"segment_urls" json:"segmentURLs" description:"分片列表JSON数组,如 [{\"timeline\":\"0.0-5.2\",\"url\":\"...\"}]"`
|
||||
AudioURL string `orm:"audio_url" json:"audioUrl" description:"提取的音频URL"`
|
||||
SceneCount int `orm:"scene_count" json:"sceneCount" description:"场景数/分片数"`
|
||||
AudioDuration float64 `orm:"audio_duration" json:"audioDuration" description:"音频时长(秒)"`
|
||||
VideoDuration float64 `orm:"video_duration" json:"videoDuration" description:"视频总时长(秒)"`
|
||||
ErrorMessage string `orm:"error_message" json:"errorMessage" description:"错误信息"`
|
||||
CallbackURL string `orm:"callback_url" json:"callbackUrl" description:"回调地址"`
|
||||
}
|
||||
|
||||
// SceneSplitTaskCol 字段定义
|
||||
type SceneSplitTaskCol struct {
|
||||
beans.SQLBaseCol
|
||||
TaskID string
|
||||
VideoURL string
|
||||
Status string
|
||||
SegmentURLs string
|
||||
AudioURL string
|
||||
SceneCount string
|
||||
AudioDuration string
|
||||
VideoDuration string
|
||||
ErrorMessage string
|
||||
CallbackURL string
|
||||
}
|
||||
|
||||
// SceneSplitTaskCols 字段常量
|
||||
var SceneSplitTaskCols = SceneSplitTaskCol{
|
||||
SQLBaseCol: beans.DefSQLBaseCol,
|
||||
TaskID: "task_id",
|
||||
VideoURL: "video_url",
|
||||
Status: "status",
|
||||
SegmentURLs: "segment_urls",
|
||||
AudioURL: "audio_url",
|
||||
SceneCount: "scene_count",
|
||||
AudioDuration: "audio_duration",
|
||||
VideoDuration: "video_duration",
|
||||
ErrorMessage: "error_message",
|
||||
CallbackURL: "callback_url",
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package video
|
||||
|
||||
import "gitea.redpowerfuture.com/red-future/common/beans"
|
||||
|
||||
// VideoAudioMergeTask 视频拼接+混音异步任务实体
|
||||
type VideoAudioMergeTask struct {
|
||||
beans.SQLBaseDO `orm:",inherit"`
|
||||
TaskID string `orm:"task_id" json:"taskId" description:"任务唯一标识"`
|
||||
VideoURLs string `orm:"video_urls" json:"videoUrls" description:"视频URL列表(JSON数组)"`
|
||||
AudioURLs string `orm:"audio_urls" json:"audioUrls" description:"音频URL列表(JSON数组)"`
|
||||
Status string `orm:"status" json:"status" description:"任务状态:pending/running/success/failed"`
|
||||
FileURL string `orm:"file_url" json:"fileUrl" description:"MinIO文件访问路径"`
|
||||
FileSize int64 `orm:"file_size" json:"fileSize" description:"文件大小(字节)"`
|
||||
FileName string `orm:"file_name" json:"fileName" description:"文件名"`
|
||||
FileFormat string `orm:"file_format" json:"fileFormat" description:"文件格式"`
|
||||
FileAddressPrefix string `orm:"file_address_prefix" json:"fileAddressPrefix" description:"MinIO地址前缀"`
|
||||
DurationStr string `orm:"duration_str" json:"durationStr" description:"合并后视频时长"`
|
||||
ErrorMessage string `orm:"error_message" json:"errorMessage" description:"错误信息"`
|
||||
CallbackURL string `orm:"callback_url" json:"callbackUrl" description:"回调地址"`
|
||||
}
|
||||
|
||||
// VideoAudioMergeTaskCol 字段定义
|
||||
type VideoAudioMergeTaskCol struct {
|
||||
beans.SQLBaseCol
|
||||
TaskID string
|
||||
VideoURLs string
|
||||
AudioURLs string
|
||||
Status string
|
||||
FileURL string
|
||||
FileSize string
|
||||
FileName string
|
||||
FileFormat string
|
||||
FileAddressPrefix string
|
||||
DurationStr string
|
||||
ErrorMessage string
|
||||
CallbackURL string
|
||||
}
|
||||
|
||||
// VideoAudioMergeTaskCols 字段常量
|
||||
var VideoAudioMergeTaskCols = VideoAudioMergeTaskCol{
|
||||
SQLBaseCol: beans.DefSQLBaseCol,
|
||||
TaskID: "task_id",
|
||||
VideoURLs: "video_urls",
|
||||
AudioURLs: "audio_urls",
|
||||
Status: "status",
|
||||
FileURL: "file_url",
|
||||
FileSize: "file_size",
|
||||
FileName: "file_name",
|
||||
FileFormat: "file_format",
|
||||
FileAddressPrefix: "file_address_prefix",
|
||||
DurationStr: "duration_str",
|
||||
ErrorMessage: "error_message",
|
||||
CallbackURL: "callback_url",
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package video
|
||||
|
||||
import (
|
||||
"gitea.redpowerfuture.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
// VideoCaptionTask 字幕叠加任务实体
|
||||
type VideoCaptionTask struct {
|
||||
beans.SQLBaseDO `orm:",inherit"`
|
||||
TaskID string `orm:"task_id" json:"taskId" description:"任务唯一标识"`
|
||||
VideoURLs string `orm:"video_urls" json:"videoUrls" description:"视频URL列表JSON"`
|
||||
AudioURL string `orm:"audio_url" json:"audioUrl" description:"背景音乐URL"`
|
||||
Elements string `orm:"elements" json:"elements" description:"字幕元素列表JSON"`
|
||||
Width int `orm:"width" json:"width" description:"视频宽度"`
|
||||
Height int `orm:"height" json:"height" description:"视频高度"`
|
||||
Status string `orm:"status" json:"status" description:"任务状态"`
|
||||
FileURL string `orm:"file_url" json:"fileUrl" description:"输出文件URL"`
|
||||
FileSize int64 `orm:"file_size" json:"fileSize" description:"输出文件大小"`
|
||||
FileName string `orm:"file_name" json:"fileName" description:"输出文件名"`
|
||||
DurationStr string `orm:"duration_str" json:"durationStr" description:"视频时长"`
|
||||
ErrorMessage string `orm:"error_message" json:"errorMessage" description:"错误信息"`
|
||||
CallbackURL string `orm:"callback_url" json:"callbackUrl" description:"回调地址"`
|
||||
}
|
||||
|
||||
// VideoCaptionTaskCol 数据库字段名常量
|
||||
type VideoCaptionTaskCol struct {
|
||||
beans.SQLBaseCol
|
||||
TaskID string
|
||||
VideoURLs string
|
||||
AudioURL string
|
||||
Elements string
|
||||
Width string
|
||||
Height string
|
||||
Status string
|
||||
FileURL string
|
||||
FileSize string
|
||||
FileName string
|
||||
DurationStr string
|
||||
ErrorMessage string
|
||||
CallbackURL string
|
||||
}
|
||||
|
||||
// VideoCaptionTaskCols 字段名常量实例
|
||||
var VideoCaptionTaskCols = VideoCaptionTaskCol{
|
||||
SQLBaseCol: beans.DefSQLBaseCol,
|
||||
TaskID: "task_id",
|
||||
VideoURLs: "video_urls",
|
||||
AudioURL: "audio_url",
|
||||
Elements: "elements",
|
||||
Width: "width",
|
||||
Height: "height",
|
||||
Status: "status",
|
||||
FileURL: "file_url",
|
||||
FileSize: "file_size",
|
||||
FileName: "file_name",
|
||||
DurationStr: "duration_str",
|
||||
ErrorMessage: "error_message",
|
||||
CallbackURL: "callback_url",
|
||||
}
|
||||
Reference in New Issue
Block a user