package api import ( "fmt" "time" "contentSecurityDemo/conf" "contentSecurityDemo/internal/model" openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client" green20220302 "github.com/alibabacloud-go/green-20220302/v2/client" util "github.com/alibabacloud-go/tea-utils/v2/service" "github.com/alibabacloud-go/tea/tea" ) // VideoScanner 视频内容安全扫描器2.0 type VideoScanner struct { Client *green20220302.Client Config *conf.Config } // VideoServiceType 视频审核服务类型 type VideoServiceType string const ( // VideoBaselineCheckGlobal 视频文件检测 VideoBaselineCheckGlobal VideoServiceType = "videoDetection_global" // VideoPostCheckByVLGlobal 视频文件检测_大模型版 VideoPostCheckByVLGlobal VideoServiceType = "videoDetectionByVL_global" ) // NewVideoScanner 创建视频扫描器 func NewVideoScanner(config *conf.Config) (*VideoScanner, error) { // 获取有效的访问凭证 accessKeyID, accessKeySecret, securityToken := config.GetEffectiveCredentials() // 创建配置 clientConfig := &openapi.Config{ AccessKeyId: tea.String(accessKeyID), AccessKeySecret: tea.String(accessKeySecret), SecurityToken: tea.String(securityToken), RegionId: tea.String(config.Region), Endpoint: tea.String(config.Endpoint), } // 创建客户端 client, err := green20220302.NewClient(clientConfig) if err != nil { return nil, fmt.Errorf("创建客户端失败: %v", err) } return &VideoScanner{ Client: client, Config: config, }, nil } // ScanVideoAsync 异步扫描视频 func (s *VideoScanner) ScanVideoAsync(videoURL string, dataID string, serviceType VideoServiceType) (*model.VideoScanResponse, error) { // 创建运行时配置 runtime := &util.RuntimeOptions{} runtime.ReadTimeout = tea.Int(10000) runtime.ConnectTimeout = tea.Int(10000) // 构建请求参数 videoScanRequest := &green20220302.VideoModerationRequest{ Service: tea.String(string(serviceType)), ServiceParameters: tea.String(fmt.Sprintf(`{"url":"%s","dataId":"%s"}`, videoURL, dataID)), } // 调用API response, err := s.Client.VideoModerationWithOptions(videoScanRequest, runtime) if err != nil { return nil, fmt.Errorf("请求失败: %v", err) } // 转换响应格式 scanResponse := &model.VideoScanResponse{ Code: tea.Int32Value(response.Body.Code), Message: tea.StringValue(response.Body.Message), Data: make([]model.VideoScanData, 0), } // 创建单个数据项 scanData := model.VideoScanData{ DataID: tea.StringValue(response.Body.Data.DataId), TaskID: tea.StringValue(response.Body.Data.TaskId), Code: tea.Int32Value(response.Body.Code), Message: tea.StringValue(response.Body.Message), URL: videoURL, } scanResponse.Data = append(scanResponse.Data, scanData) return scanResponse, nil } // GetVideoResult 获取视频审核结果 func (s *VideoScanner) GetVideoResult(taskID string, serviceType VideoServiceType) (*model.VideoResultResponse, error) { // 创建运行时配置 runtime := &util.RuntimeOptions{} runtime.ReadTimeout = tea.Int(10000) runtime.ConnectTimeout = tea.Int(10000) // 构建请求参数 videoResultRequest := &green20220302.VideoModerationResultRequest{ Service: tea.String(string(serviceType)), ServiceParameters: tea.String(fmt.Sprintf(`{"taskId":"%s"}`, taskID)), } // 调用API response, err := s.Client.VideoModerationResultWithOptions(videoResultRequest, runtime) if err != nil { return nil, fmt.Errorf("请求失败: %v", err) } // 转换响应格式 resultResponse := &model.VideoResultResponse{ Code: tea.Int32Value(response.Body.Code), Message: tea.StringValue(response.Body.Message), Data: make([]model.VideoResultData, 0), } // 创建单个数据项 resultData := model.VideoResultData{ Code: tea.Int32Value(response.Body.Code), Message: tea.StringValue(response.Body.Message), } if tea.StringValue(response.Body.Message) == "SUCCESS" { resultData.Status = "success" } else if tea.StringValue(response.Body.Message) == "PROCESSING" { resultData.Status = "pending" } else { resultData.Status = "failure" } // 如果有结果数据,进行转换 if response.Body.Data != nil { resultData.DataID = tea.StringValue(response.Body.Data.DataId) resultData.TaskID = tea.StringValue(response.Body.Data.TaskId) resultData.Results = response.Body.Data } resultResponse.Data = append(resultResponse.Data, resultData) return resultResponse, nil } // ScanVideoAndWait 扫描视频并等待结果 func (s *VideoScanner) ScanVideoAndWait(videoURL string, dataID string, serviceType VideoServiceType, maxWaitTime time.Duration) (*model.VideoResultResponse, error) { // 提交扫描任务 scanResponse, err := s.ScanVideoAsync(videoURL, dataID, serviceType) if err != nil { return nil, fmt.Errorf("提交扫描任务失败: %v", err) } if len(scanResponse.Data) == 0 { return nil, fmt.Errorf("未获取到任务ID") } taskID := scanResponse.Data[0].TaskID fmt.Printf("视频扫描任务已提交,任务ID: %s\n", taskID) // 轮询获取结果 startTime := time.Now() for time.Since(startTime) < maxWaitTime { result, err := s.GetVideoResult(taskID, serviceType) if err != nil { return nil, fmt.Errorf("获取结果失败: %v", err) } if len(result.Data) > 0 { status := result.Data[0].Status fmt.Printf("当前状态: %s\n", status) switch status { case "success": return result, nil case "failure": return nil, fmt.Errorf("视频审核失败: %s", result.Data[0].Message) case "running", "pending": // 继续等待 time.Sleep(5 * time.Second) default: return nil, fmt.Errorf("未知状态: %s", status) } } else { time.Sleep(5 * time.Second) } } return nil, fmt.Errorf("等待超时,请稍后手动查询结果,任务ID: %s", taskID) } // PrintScanResult 打印扫描提交结果 func (s *VideoScanner) PrintScanResult(response *model.VideoScanResponse) { fmt.Println("=== 视频扫描任务提交结果 ===") fmt.Printf("状态码: %d\n", response.Code) fmt.Printf("消息: %s\n", response.Message) for _, data := range response.Data { fmt.Printf("数据ID: %s\n", data.DataID) fmt.Printf("任务ID: %s\n", data.TaskID) fmt.Printf("处理状态: %d - %s\n", data.Code, data.Message) fmt.Printf("视频URL: %s\n", data.URL) } } // PrintResult 打印审核结果 func (s *VideoScanner) PrintResult(response *model.VideoResultResponse) { fmt.Println("=== 视频内容安全审核结果===") fmt.Printf("状态码: %d\n", response.Code) fmt.Printf("消息: %s\n", response.Message) for _, data := range response.Data { fmt.Printf("\n数据ID: %s\n", data.DataID) fmt.Printf("任务ID: %s\n", data.TaskID) fmt.Printf("处理状态: %d - %s\n", data.Code, data.Message) fmt.Printf("审核状态: %s\n", data.Status) if data.Results != nil { result := *data.Results if result.LiveId != nil { fmt.Printf("直播ID: %s\n", *result.LiveId) } if result.ManualTaskId != nil { fmt.Printf("人工任务ID: %s\n", *result.ManualTaskId) } if result.RiskLevel != nil { fmt.Printf("风险等级: %s\n", *result.RiskLevel) } // 打印详细信息 if result.AudioResult != nil { fmt.Println("音频审核结果:") audioResult := *result.AudioResult if audioResult.RiskLevel != nil { fmt.Printf("风险等级: %s\n", *audioResult.RiskLevel) } } // 打印扩展信息 if result.FrameResult != nil { fmt.Println("帧审核结果:") frameResult := *result.FrameResult if frameResult.RiskLevel != nil { fmt.Printf("风险等级: %s\n", *frameResult.RiskLevel) } } fmt.Println("---") } } }