Files
cid/service/yidun/video_detection_service.go
2026-05-15 10:28:17 +08:00

657 lines
28 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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不能为空")
}
g.Log().Infof(ctx, "视频检测任务提交, url: %s, dataID: %s", videoURL, dataID)
// 创建请求
req := vsrequest.NewVideoSolutionSubmitV2Req()
req.SetURL(videoURL)
req.SetDataID(dataID)
req.SetUniqueKey(dataID)
// 设置回调地址
if callbackURL != "" {
req.SetCallbackURL(callbackURL)
}
// 设置子产品标识(视频解决方案必须)
req.SetSubProduct("videoStream")
// 可选设置IP用于风险用户识别
// req.SetIP("127.0.0.1")
// 调用API
response, err := DefaultClients.VideoClient.Submit(req)
if err != nil {
g.Log().Errorf(ctx, "视频检测提交HTTP错误: %v", err)
return nil, fmt.Errorf("视频检测提交HTTP错误: %w", err)
}
if response.GetCode() != 200 {
g.Log().Errorf(ctx, "视频检测API错误: code=%d, msg=%s", response.GetCode(), response.GetMsg())
// 根据错误码提供更详细的错误信息
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)
}
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)
return nil, ErrVideoResultNotFound
}
// 查找指定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
}