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 }