Files
cid/service/yidun/video_detection_service.go

657 lines
28 KiB
Go
Raw Normal View History

2026-05-08 09:33:40 +08:00
package yidun
import (
"context"
"encoding/json"
"errors"
"fmt"
"github.com/gogf/gf/v2/frame/g"
audiocallback "github.com/yidun/yidun-golang-sdk/yidun/service/antispam/audio/callback/v4/response"
videocallback "github.com/yidun/yidun-golang-sdk/yidun/service/antispam/video/callback/v4/response"
callbackrequest "github.com/yidun/yidun-golang-sdk/yidun/service/antispam/videosolution/callback/v2/request"
callbackresponse "github.com/yidun/yidun-golang-sdk/yidun/service/antispam/videosolution/callback/v2/response"
vsrequest "github.com/yidun/yidun-golang-sdk/yidun/service/antispam/videosolution/submit/v2/request"
)
// VideoDetectionService 视频检测服务
type VideoDetectionService struct{}
var VideoDetection = new(VideoDetectionService)
var (
ErrVideoStillProcessing = errors.New("视频仍在检测中,请稍后重试")
ErrVideoResultNotFound = errors.New("未找到视频检测结果")
)
// VideoSubmitResult 视频检测提交结果
type VideoSubmitResult struct {
TaskID string `json:"taskId"` // 任务ID
DataID string `json:"dataId"` // 数据ID
DealingCount int64 `json:"dealingCount"` // 缓冲池排队待处理数据量
}
// DetectVideo 提交视频检测任务,返回完整响应
func (s *VideoDetectionService) DetectVideo(ctx context.Context, videoURL, dataID string, callbackURL string) (*VideoSubmitResult, error) {
if DefaultClients == nil || DefaultClients.VideoClient == nil {
return nil, fmt.Errorf("易盾视频检测客户端未初始化")
}
if videoURL == "" {
return nil, fmt.Errorf("视频URL不能为空")
}
2026-05-15 10:28:17 +08:00
g.Log().Infof(ctx, "视频检测任务提交, url: %s, dataID: %s", videoURL, dataID)
2026-05-08 09:33:40 +08:00
// 创建请求
req := vsrequest.NewVideoSolutionSubmitV2Req()
req.SetURL(videoURL)
req.SetDataID(dataID)
req.SetUniqueKey(dataID)
2026-05-15 10:28:17 +08:00
// 设置回调地址
2026-05-08 09:33:40 +08:00
if callbackURL != "" {
req.SetCallbackURL(callbackURL)
}
2026-05-15 10:28:17 +08:00
// 设置子产品标识(视频解决方案必须)
req.SetSubProduct("videoStream")
// 可选设置IP用于风险用户识别
// req.SetIP("127.0.0.1")
2026-05-08 09:33:40 +08:00
// 调用API
response, err := DefaultClients.VideoClient.Submit(req)
if err != nil {
2026-05-15 10:28:17 +08:00
g.Log().Errorf(ctx, "视频检测提交HTTP错误: %v", err)
return nil, fmt.Errorf("视频检测提交HTTP错误: %w", err)
2026-05-08 09:33:40 +08:00
}
if response.GetCode() != 200 {
g.Log().Errorf(ctx, "视频检测API错误: code=%d, msg=%s", response.GetCode(), response.GetMsg())
2026-05-15 10:28:17 +08:00
// 根据错误码提供更详细的错误信息
errMsg := fmt.Sprintf("视频检测API错误: code=%d, msg=%s", response.GetCode(), response.GetMsg())
// 常见错误码说明
switch response.GetCode() {
case 417:
errMsg += " (可能原因: 视频URL无法访问或业务配置问题)"
case 400:
errMsg += " (可能原因: 请求参数错误)"
case 403:
errMsg += " (可能原因: 鉴权失败检查secretId和secretKey)"
}
return nil, fmt.Errorf(errMsg)
2026-05-08 09:33:40 +08:00
}
result := &VideoSubmitResult{}
if response.Result != nil {
if response.Result.TaskID != nil {
result.TaskID = *response.Result.TaskID
}
if response.Result.DataID != nil {
result.DataID = *response.Result.DataID
}
if response.Result.DealingCount != nil {
result.DealingCount = *response.Result.DealingCount
}
}
g.Log().Infof(ctx, "视频检测任务提交成功, taskID: %s, dealingCount: %d", result.TaskID, result.DealingCount)
return result, nil
}
// VideoResult 视频检测完整结果
// 包含易盾返回的完整检测信息文本、图片、音频、ASR等
type VideoResult struct {
TaskID string `json:"taskId"` // 任务ID
Status int `json:"status"` // 检测状态0=未开始1=检测中2=检测完成
Suggestion int `json:"suggestion"` // 处置建议0=通过1=嫌疑2=不通过
Label int `json:"label"` // 垃圾类型
ResultType int `json:"resultType"` // 结果类型1=机器结果2=人审结果
DataID string `json:"dataId"` // 数据ID
CensorTime int64 `json:"censorTime"` // 审核完成时间(毫秒)
Duration int64 `json:"duration"` // 视频时长(毫秒)
// 完整证据信息
Antispam *callbackresponse.VideoSolutionAntispamCallbackV2Response `json:"antispam,omitempty"` // 反垃圾检测结果
Language *audiocallback.AudioLanguageCallbackV4Response `json:"language,omitempty"` // 语言检测结果
Voice *audiocallback.AudioVoiceCallbackV4Response `json:"voice,omitempty"` // 语音识别结果
Asr *audiocallback.AudioAsrCallbackV4Response `json:"asr,omitempty"` // ASR语音转文字结果
Ocr *videocallback.VideoCallbackOcrV4Response `json:"ocr,omitempty"` // OCR文字识别结果
Discern *videocallback.VideoCallbackDiscernV4Response `json:"discern,omitempty"` // 画面识别结果
Logo *videocallback.VideoCallbackLogoV4Response `json:"logo,omitempty"` // Logo识别结果
Face *videocallback.VideoCallbackFaceV4Response `json:"face,omitempty"` // 人脸识别结果
Aigc *videocallback.VideoCallbackAigcV4Response `json:"aigc,omitempty"` // AIGC识别结果
Quality *callbackresponse.VideoSolutionQualityCallbackV2Response `json:"quality,omitempty"` // 音视频质量检测结果
}
// GetVideoResult 获取视频检测结果(轮询模式)
// 返回完整的检测详情包括文本、图片、音频、ASR等
func (s *VideoDetectionService) GetVideoResult(ctx context.Context, taskID string) (*VideoResult, error) {
if DefaultClients == nil || DefaultClients.VideoClient == nil {
return nil, fmt.Errorf("易盾视频检测客户端未初始化")
}
g.Log().Infof(ctx, "查询视频检测结果, taskID: %s", taskID)
req := callbackrequest.NewVideoSolutionCallbackV2Request()
req.SetYidunRequestId(taskID)
response, err := DefaultClients.VideoClient.Callback(req)
if err != nil {
g.Log().Errorf(ctx, "查询视频检测结果失败: %v", err)
return nil, fmt.Errorf("查询视频检测结果失败: %w", err)
}
if response.GetCode() != 200 {
g.Log().Errorf(ctx, "查询视频检测结果API错误: code=%d, msg=%s", response.GetCode(), response.GetMsg())
return nil, fmt.Errorf("查询视频检测结果API错误: code=%d, msg=%s", response.GetCode(), response.GetMsg())
}
if response.Result == nil || len(*response.Result) == 0 {
g.Log().Warningf(ctx, "未找到视频检测结果, taskID: %s", taskID)
2026-05-15 10:28:17 +08:00
return nil, ErrVideoResultNotFound
2026-05-08 09:33:40 +08:00
}
// 查找指定taskID的结果
for _, item := range *response.Result {
if item.Antispam != nil && item.Antispam.TaskID != nil && *item.Antispam.TaskID == taskID {
result := &VideoResult{
Antispam: item.Antispam,
Language: item.Language,
Voice: item.Voice,
Asr: item.Asr,
Ocr: item.Ocr,
Discern: item.Discern,
Logo: item.Logo,
Face: item.Face,
Aigc: item.Aigc,
Quality: item.Quality,
}
result.TaskID = taskID
if item.Antispam.Status != nil {
result.Status = *item.Antispam.Status
}
if item.Antispam.Suggestion != nil {
result.Suggestion = *item.Antispam.Suggestion
}
if item.Antispam.Label != nil {
result.Label = *item.Antispam.Label
}
if item.Antispam.ResultType != nil {
result.ResultType = *item.Antispam.ResultType
}
if item.Antispam.DataID != nil {
result.DataID = *item.Antispam.DataID
}
if item.Antispam.CensorTime != nil {
result.CensorTime = *item.Antispam.CensorTime
}
if item.Antispam.Duration != nil {
result.Duration = *item.Antispam.Duration
}
return result, nil
}
}
g.Log().Warningf(ctx, "未找到指定的taskID: %s", taskID)
return nil, ErrVideoResultNotFound
}
// =============================================================================
// 视频检测结果推送模式(易盾主动回调)
// =============================================================================
// VideoCallbackData 推送模式回调数据完整结构
type VideoCallbackData struct {
Antispam *VideoCallbackAntispam `json:"antispam"` // 反垃圾检测结果
}
type VideoCallbackAntispam struct {
TaskID string `json:"taskId"` // 任务ID
DataID string `json:"dataId"` // 客户数据ID
Callback string `json:"callback"` // 回调参数
Suggestion int `json:"suggestion"` // 处置建议0=通过1=嫌疑2=不通过
Status int `json:"status"` // 检测状态0=未开始1=检测中2=检测成功3=检测失败
ResultType int `json:"resultType"` // 结果类型1=机器结果2=人审结果
CensorRound int `json:"censorRound"` // 人审轮次
Censor string `json:"censor"` // 人审操作人
CensorSource int `json:"censorSource"` // 审核来源0=易盾人审1=客户人审2=易盾机审
CheckTime int64 `json:"checkTime"` // 机器检测结束时间
CensorTime int64 `json:"censorTime"` // 人工审核完成时间
Duration int64 `json:"duration"` // 音视频时长(毫秒)
DurationMs int64 `json:"durationMs"` // 音频时长(毫秒)
Label int `json:"label"` // 一级垃圾类型
SecondLabel string `json:"secondLabel"` // 二级垃圾类型
ThirdLabel string `json:"thirdLabel"` // 三级垃圾类型
RiskDescription string `json:"riskDescription"` // 风险描述
PicCount int64 `json:"picCount"` // 截图数量
CensorLabels []*VideoCensorLabel `json:"censorLabels"` // 审核标签
CensorExtension *VideoCensorExtension `json:"censorExtension"` // 质检扩展结果
Evidences *VideoCallbackEvidence `json:"evidences"` // 机器检测证据信息
SolutionExtra *VideoSolutionExtra `json:"solutionExtra"` // 额外信息
ReviewEvidences *VideoReviewEvidence `json:"reviewEvidences"` // 人审证据信息
}
// VideoCensorLabel 审核标签
type VideoCensorLabel struct {
Code string `json:"code"` // 审核标签编码
Desc string `json:"desc"` // 审核标签描述
Name string `json:"name"` // 审核标签名称
CustomCode string `json:"customCode"` // 自定义标签编码
ParentLabelId string `json:"parentLabelId"` // 父标签ID
Depth int `json:"depth"` // 标签深度
}
// VideoCensorExtension 质检扩展结果
type VideoCensorExtension struct {
QualityInspectionTaskId string `json:"qualityInspectionTaskId"` // 质检任务ID
QualityInspectionType int `json:"qualityInspectionType"` // 质检类型
InspTaskCreateTime int64 `json:"inspTaskCreateTime"` // 质检任务创建时间
}
// VideoCallbackEvidence 机器检测证据信息
type VideoCallbackEvidence struct {
Text *VideoTextEvidence `json:"text,omitempty"` // 文本证据
Images *[]VideoImageEvidence `json:"images,omitempty"` // 图片证据
Audio *VideoAudioEvidence `json:"audio,omitempty"` // 音频证据
Video *VideoVideoEvidence `json:"video,omitempty"` // 视频证据
}
// VideoTextEvidence 文本证据
type VideoTextEvidence struct {
TaskID string `json:"taskId"` // 任务ID
DataID string `json:"dataId"` // 数据ID
Suggestion int `json:"suggestion"` // 处置建议
ResultType int `json:"resultType"` // 结果类型
CensorType int `json:"censorType"` // 审核类型
IsRelatedHit bool `json:"isRelatedHit"` // 是否关联命中
Labels []*VideoTextLabel `json:"labels"` // 分类标签
}
// VideoTextLabel 文本分类标签
type VideoTextLabel struct {
Label int `json:"label"` // 标签类型
Level int `json:"level"` // 级别
SubLabels []*VideoTextSubLabel `json:"subLabels"` // 二级分类
}
// VideoTextSubLabel 文本二级分类
type VideoTextSubLabel struct {
SubLabel string `json:"subLabel"` // 二级分类
SubLabelDepth int `json:"subLabelDepth"` // 细分类层级
SecondLabel string `json:"secondLabel"` // 二级分类
ThirdLabel string `json:"thirdLabel"` // 三级分类
Details *VideoTextSubLabelDetail `json:"details"` // 命中详情
}
// VideoTextSubLabelDetail 文本二级分类命中详情
type VideoTextSubLabelDetail struct {
Keywords *[]VideoTextKeyword `json:"keywords,omitempty"` // 敏感词
LibInfos *[]VideoTextLibInfo `json:"libInfos,omitempty"` // 名单信息
Anticheat *VideoTextAnticheat `json:"anticheat,omitempty"` // 反作弊
HitInfos *[]VideoTextHitInfo `json:"hitInfos,omitempty"` // 其他命中
}
// VideoTextKeyword 敏感词信息
type VideoTextKeyword struct {
Word string `json:"word"` // 敏感词
StrategyGroupId int64 `json:"strategyGroupId"` // 策略组ID
StrategyGroupName string `json:"strategyGroupName"` // 策略组名称
}
// VideoTextLibInfo 名单信息
type VideoTextLibInfo struct {
Type int `json:"type"` // 名单类型
Entity string `json:"entity"` // 名单内容
ReleaseTime int64 `json:"releaseTime"` // 释放时间
}
// VideoTextAnticheat 反作弊信息
type VideoTextAnticheat struct {
HitType int `json:"hitType"` // 命中类型
}
// VideoTextHitInfo 其他命中信息
type VideoTextHitInfo struct {
Value string `json:"value"` // 命中值
Positions *[]VideoTextHitPosition `json:"positions"` // 命中位置
}
// VideoTextHitPosition 命中位置
type VideoTextHitPosition struct {
FieldName string `json:"fieldName"` // 字段名
StartPos int `json:"startPos"` // 开始位置
EndPos int `json:"endPos"` // 结束位置
}
// VideoImageEvidence 图片证据
type VideoImageEvidence struct {
Name string `json:"name"` // 图片名称
DataID string `json:"dataId"` // 数据ID
Suggestion int `json:"suggestion"` // 处置建议
ResultType int `json:"resultType"` // 结果类型
Status int `json:"status"` // 状态
CensorType int `json:"censorType"` // 审核类型
Labels []*VideoImageLabel `json:"labels"` // 分类标签
TaskId string `json:"taskId"` // 任务ID
}
// VideoImageLabel 图片分类标签
type VideoImageLabel struct {
Label int `json:"label"` // 标签类型
Level int `json:"level"` // 级别
Rate float32 `json:"rate"` // 置信度
SubLabels []*VideoImageSubLabel `json:"subLabels"` // 二级分类
}
// VideoImageSubLabel 图片二级分类
type VideoImageSubLabel struct {
SubLabel interface{} `json:"subLabel"` // 二级分类标签
SubLabelDepth int `json:"subLabelDepth"` // 细分类层级
SecondLabel string `json:"secondLabel"` // 二级分类
ThirdLabel string `json:"thirdLabel"` // 三级分类
HitStrategy int `json:"hitStrategy"` // 命中策略
Rate float32 `json:"rate"` // 置信度
Details *VideoImageSubDetail `json:"details"` // 命中详情
Explain string `json:"explain"` // 解释
IsLlmCheck bool `json:"isLlmCheck"` // 是否LLM命中
}
// VideoImageSubDetail 图片二级分类命中详情
type VideoImageSubDetail struct {
Keywords *[]VideoImageHitInfo `json:"keywords,omitempty"` // 敏感词
LibInfos *[]VideoImageLibInfo `json:"libInfos,omitempty"` // 名单信息
HitInfos *[]VideoImageHitInfo `json:"hitInfos,omitempty"` // 其他命中
Anticheat *VideoImageAnticheat `json:"anticheat,omitempty"` // 反作弊
Llm *VideoImageLlm `json:"llm,omitempty"` // 大模型
}
// VideoImageHitInfo 图片命中信息
type VideoImageHitInfo struct {
Type int `json:"type"` // 命中类型
Word string `json:"word"` // 敏感词
Entity string `json:"entity"` // 名单URL
HitCount int `json:"hitCount"` // 命中次数
Value string `json:"value"` // 值
Group string `json:"group"` // 分组
X1 float32 `json:"x1"` // 坐标
Y1 float32 `json:"y1"` // 坐标
X2 float32 `json:"x2"` // 坐标
Y2 float32 `json:"y2"` // 坐标
StrategyGroupName string `json:"strategyGroupName"` // 策略组名称
StrategyGroupId int64 `json:"strategyGroupId"` // 策略组ID
}
// VideoImageLibInfo 图片名单信息
type VideoImageLibInfo struct {
Type int `json:"type"` // 名单类型
Entity string `json:"entity"` // 名单URL
HitCount int `json:"hitCount"` // 命中次数
ReleaseTime int64 `json:"releaseTime"` // 释放时间
StrategyGroupName string `json:"strategyGroupName"` // 策略组名称
StrategyGroupId int64 `json:"strategyGroupId"` // 策略组ID
}
// VideoImageAnticheat 反作弊信息
type VideoImageAnticheat struct {
HitType int `json:"hitType"` // 命中类型
}
// VideoImageLlm 大模型信息
type VideoImageLlm struct {
Keyword string `json:"keyword"` // 关键词
}
// VideoAudioEvidence 音频证据
type VideoAudioEvidence struct {
TaskID string `json:"taskId"` // 任务ID
DataID string `json:"dataId"` // 数据ID
Status int `json:"status"` // 状态
Suggestion int `json:"suggestion"` // 处置建议
Label int `json:"label"` // 标签
ResultType int `json:"resultType"` // 结果类型
Callback string `json:"callback"` // 回调参数
CensorSource int `json:"censorSource"` // 审核来源
CensorTime int64 `json:"censorTime"` // 审核时间
Duration int64 `json:"duration"` // 音频时长
Segments []*VideoAudioSegment `json:"segments"` // 音频片段
}
// VideoAudioSegment 音频片段
type VideoAudioSegment struct {
StartTime int `json:"startTime"` // 开始时间(秒)
EndTime int `json:"endTime"` // 结束时间(秒)
StartTimeMillis int64 `json:"startTimeMillis"` // 开始时间(毫秒)
EndTimeMillis int64 `json:"endTimeMillis"` // 结束时间(毫秒)
Content string `json:"content"` // 语音识别原文
Type int `json:"type"` // 片段类型0=语音识别1=声纹检测
LeaderName string `json:"leaderName"` // 声纹检测人名
Labels []*VideoAudioLabel `json:"labels"` // 分类标签
Url string `json:"url"` // 音频URL
}
// VideoAudioLabel 音频分类标签
type VideoAudioLabel struct {
Label int `json:"label"` // 标签类型
Level int `json:"level"` // 级别
SubLabels []*VideoAudioSubLabel `json:"subLabels"` // 二级分类
}
// VideoAudioSubLabel 音频二级分类
type VideoAudioSubLabel struct {
SubLabel string `json:"subLabel"` // 细分类
SubLabelDepth int `json:"subLabelDepth"` // 细分类层级
SecondLabel string `json:"secondLabel"` // 二级分类
ThirdLabel string `json:"thirdLabel"` // 三级分类
SuggestionRiskLevel int `json:"suggestionRiskLevel"` // 嫌疑级别
Rate float64 `json:"rate"` // 置信度
RiskDescription string `json:"riskDescription"` // 风险描述
Details *VideoAudioSubLabelDetail `json:"details"` // 命中详情
}
// VideoAudioSubLabelDetail 音频二级分类命中详情
type VideoAudioSubLabelDetail struct {
HitInfos *[]VideoAudioHitInfo `json:"hitInfos,omitempty"` // 命中内容
Keywords *[]VideoAudioKeyword `json:"keywords,omitempty"` // 自定义敏感词
LibInfos *[]VideoAudioLibInfo `json:"libInfos,omitempty"` // 自定义名单
}
// VideoAudioHitInfo 音频命中内容
type VideoAudioHitInfo struct {
Value string `json:"value"` // 命中敏感词或声纹检测分值
StartTime int `json:"startTime"` // 开始时间
EndTime int `json:"endTime"` // 结束时间
}
// VideoAudioKeyword 自定义敏感词
type VideoAudioKeyword struct {
Word string `json:"word"` // 敏感词
StrategyGroupName string `json:"strategyGroupName"` // 策略组名称
StrategyGroupId int64 `json:"strategyGroupId"` // 策略组ID
}
// VideoAudioLibInfo 自定义名单
type VideoAudioLibInfo struct {
ListType int `json:"listType"` // 名单类型
Entity string `json:"entity"` // 名单内容
}
// VideoVideoEvidence 视频证据
type VideoVideoEvidence struct {
TaskID string `json:"taskId"` // 任务ID
DataID string `json:"dataId"` // 数据ID
Status int `json:"status"` // 状态
Suggestion int `json:"suggestion"` // 处置建议
ResultType int `json:"resultType"` // 结果类型
CensorSource int `json:"censorSource"` // 审核来源
CensorTime int64 `json:"censorTime"` // 审核时间
Pictures []*VideoPicture `json:"pictures"` // 截图列表
}
// VideoPicture 截图信息
type VideoPicture struct {
Type int `json:"type"` // 类型
URL string `json:"url"` // 图片URL
StartTime int64 `json:"startTime"` // 开始时间
EndTime int64 `json:"endTime"` // 结束时间
Labels []*VideoPictureLabel `json:"labels"` // 分类标签
CensorSource int `json:"censorSource"` // 审核来源
FrontPics []*VideoRelatedPic `json:"frontPics"` // 关联前帧
BackPics []*VideoRelatedPic `json:"backPics"` // 关联后帧
PictureID string `json:"pictureId"` // 图片ID
}
// VideoPictureLabel 截图分类标签
type VideoPictureLabel struct {
Label int `json:"label"` // 标签类型
Level int `json:"level"` // 级别
Rate float32 `json:"rate"` // 置信度
SubLabels []*VideoPictureSubLabel `json:"subLabels"` // 二级分类
}
// VideoPictureSubLabel 截图二级分类
type VideoPictureSubLabel struct {
SubLabel interface{} `json:"subLabel"` // 二级分类标签
SubLabelDepth int `json:"subLabelDepth"` // 细分类层级
SecondLabel string `json:"secondLabel"` // 二级分类
ThirdLabel string `json:"thirdLabel"` // 三级分类
HitStrategy int `json:"hitStrategy"` // 命中策略
Rate float32 `json:"rate"` // 置信度
Details *VideoPictureSubDetail `json:"details"` // 命中详情
Explain string `json:"explain"` // 解释
IsLlmCheck bool `json:"isLlmCheck"` // 是否LLM命中
}
// VideoPictureSubDetail 截图二级分类命中详情
type VideoPictureSubDetail struct {
Keywords *[]VideoPictureHitInfo `json:"keywords,omitempty"` // 敏感词
LibInfos *[]VideoPictureLibInfo `json:"libInfos,omitempty"` // 名单信息
HitInfos *[]VideoPictureHitInfo `json:"hitInfos,omitempty"` // 其他命中
Anticheat *VideoPictureAnticheat `json:"anticheat,omitempty"` // 反作弊
Llm *VideoPictureLlm `json:"llm,omitempty"` // 大模型
}
// VideoPictureHitInfo 截图命中信息
type VideoPictureHitInfo struct {
Value string `json:"value"` // 命中值
Group string `json:"group"` // 分组
Type int `json:"type"` // 类型
X1 float32 `json:"x1"` // 坐标
Y1 float32 `json:"y1"` // 坐标
X2 float32 `json:"x2"` // 坐标
Y2 float32 `json:"y2"` // 坐标
}
// VideoPictureLibInfo 截图名单信息
type VideoPictureLibInfo struct {
Type int `json:"type"` // 名单类型
Entity string `json:"entity"` // 名单URL
HitCount int `json:"hitCount"` // 命中次数
ReleaseTime int64 `json:"releaseTime"` // 释放时间
StrategyGroupName string `json:"strategyGroupName"` // 策略组名称
StrategyGroupId int64 `json:"strategyGroupId"` // 策略组ID
}
// VideoPictureAnticheat 反作弊信息
type VideoPictureAnticheat struct {
HitType int `json:"hitType"` // 命中类型
}
// VideoPictureLlm 大模型信息
type VideoPictureLlm struct {
Keyword string `json:"keyword"` // 关键词
}
// VideoRelatedPic 关联截图
type VideoRelatedPic struct {
URL string `json:"url"` // 图片URL
}
// VideoSolutionExtra 额外信息
type VideoSolutionExtra struct {
FailUnit *VideoFailUnit `json:"failUnit,omitempty"` // 失败单元
}
// VideoFailUnit 失败单元
type VideoFailUnit struct {
Images *[]VideoImageFailUnit `json:"images,omitempty"` // 图片失败单元
Audio *VideoTargetFailUnit `json:"audio,omitempty"` // 音频失败单元
Video *VideoTargetFailUnit `json:"video,omitempty"` // 视频失败单元
}
// VideoImageFailUnit 图片失败单元
type VideoImageFailUnit struct {
FailureReason int `json:"failureReason"` // 失败原因
Name string `json:"name"` // 名称
}
// VideoTargetFailUnit 目标失败单元
type VideoTargetFailUnit struct {
FailureReason int `json:"failureReason"` // 失败原因
}
// VideoReviewEvidence 人审证据信息
type VideoReviewEvidence struct {
Description string `json:"description"` // 描述
Detail string `json:"detail"` // 详情
Texts *[]VideoReviewText `json:"texts"` // 文本证据
Images *[]VideoReviewImage `json:"images"` // 图片证据
Audios *[]VideoReviewAudio `json:"audios"` // 音频证据
Videos *[]VideoReviewVideo `json:"videos"` // 视频证据
}
// VideoReviewText 人审文本证据
type VideoReviewText struct {
Snippet string `json:"snippet"` // 片段
Description string `json:"description"` // 描述
}
// VideoReviewImage 人审图片证据
type VideoReviewImage struct {
URL string `json:"url"` // 图片URL
Description string `json:"description"` // 描述
}
// VideoReviewAudio 人审音频证据
type VideoReviewAudio struct {
StartTime int64 `json:"startTime"` // 开始时间
EndTime int64 `json:"endTime"` // 结束时间
Description string `json:"description"` // 描述
}
// VideoReviewVideo 人审视频证据
type VideoReviewVideo struct {
StartTime int64 `json:"startTime"` // 开始时间
EndTime int64 `json:"endTime"` // 结束时间
URL string `json:"url"` // 视频URL
Description string `json:"description"` // 描述
}
// ProcessVideoCallback 处理视频检测回调(推送模式)
func (s *VideoDetectionService) ProcessVideoCallback(ctx context.Context, callbackData string) error {
if callbackData == "" {
return fmt.Errorf("回调数据不能为空")
}
var data VideoCallbackData
if err := json.Unmarshal([]byte(callbackData), &data); err != nil {
g.Log().Errorf(ctx, "解析视频回调数据失败: %v", err)
return fmt.Errorf("解析视频回调数据失败: %w", err)
}
if data.Antispam == nil {
return fmt.Errorf("视频回调数据格式错误缺少antispam字段")
}
g.Log().Infof(ctx, "处理视频检测结果 - taskId: %s, suggestion: %d, resultType: %d, status: %d",
data.Antispam.TaskID, data.Antispam.Suggestion, data.Antispam.ResultType, data.Antispam.Status)
// TODO: 业务逻辑,如保存数据库、触发后续流程等
// 可使用完整字段data.Antispam.Evidences, data.Antispam.CensorLabels, data.Antispam.Duration 等
return nil
}