contentSecurity/internal/api/video_scanner.go
2025-10-16 15:21:30 +08:00

247 lines
7.3 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 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: dataID,
TaskID: fmt.Sprintf("task_%s_%d", dataID, time.Now().Unix()),
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) (*model.VideoResultResponse, error) {
// 创建运行时配置
runtime := &util.RuntimeOptions{}
runtime.ReadTimeout = tea.Int(10000)
runtime.ConnectTimeout = tea.Int(10000)
// 构建请求参数
videoResultRequest := &green20220302.VideoModerationResultRequest{
Service: tea.String("videoDetection"),
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{
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),
Status: "success",
}
// 如果有结果数据,进行转换
if response.Body.Data != nil {
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)
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("---")
}
}
}