ling-baseling-base

内容审核

文本/图片/音视频审核,阿里云/腾讯云/七牛

在线 Playground

在浏览器中直接体验本页相关 API,无需本地安装 Go 环境。

内容审核 (censor)

统一内容审核抽象,覆盖文本、图片(同步)音频、视频(异步任务)。核心包零云 SDK;阿里云、腾讯云、七牛各为独立 Go module。

架构

providers/censor/
├── censor.go    # CensorResult、JobSnapshot、Suggestion 常量
├── text.go      # TextCensor 接口
├── image.go     # ImageCensor 接口
├── audio.go     # AudioCensor 接口
├── video.go     # VideoCensor 接口
├── aliyun/      # 阿里云内容安全
├── qcloud/      # 腾讯云天御
└── qiniu/       # 七牛审核

安装

go get github.com/LingByte/ling-base/providers/censor
go get github.com/LingByte/ling-base/providers/censor/aliyun
go get github.com/LingByte/ling-base/providers/censor/qcloud
go get github.com/LingByte/ling-base/providers/censor/qiniu

统一类型

CensorResult(同步:文本、图片)

字段说明
Suggestionpass / review / block
Labelnormal / spam / porn / politics / ...
Score置信度 0.0–1.0
Details厂商扩展信息
Msg英文可读描述

JobSnapshot(异步:音频、视频)

字段说明
StatusWAITING / DOING / FINISHED / FAILED
Suggestion / Label / Score任务完成时填充
Error失败原因
Raw原始厂商响应
import "github.com/LingByte/ling-base/providers/censor"

switch result.Suggestion {
case censor.SuggestionPass:
    // 放行
case censor.SuggestionReview:
    // 人工复审
case censor.SuggestionBlock:
    // 拦截
}

接口一览

// 同步
type TextCensor interface {
    CensorText(ctx context.Context, text string) (*CensorResult, error)
}
type ImageCensor interface {
    CensorImage(ctx context.Context, imageURL string) (*CensorResult, error)
}

// 异步:Submit → 轮询 GetCensorResult
type AudioCensor interface {
    SubmitCensorAudio(ctx context.Context, audioURL string) (taskID string, err error)
    GetCensorResult(ctx context.Context, taskID string) (*JobSnapshot, error)
}
type VideoCensor interface {
    SubmitCensorVideo(ctx context.Context, videoURL string) (taskID string, err error)
    GetCensorResult(ctx context.Context, taskID string) (*JobSnapshot, error)
}

文本审核(同步)

七牛

import (
    "context"
    "github.com/LingByte/ling-base/providers/censor"
    qiniu "github.com/LingByte/ling-base/providers/censor/qiniu"
)

c, err := qiniu.NewTextCensor(qiniu.Config{
    AccessKey: "your-access-key",
    SecretKey: "your-secret-key",
})
if err != nil {
    panic(err)
}

result, err := c.CensorText(context.Background(), "待审核的用户评论内容")
fmt.Printf("suggestion=%s label=%s score=%.2f\n",
    result.Suggestion, result.Label, result.Score)

阿里云

import aliyun "github.com/LingByte/ling-base/providers/censor/aliyun"

c, err := aliyun.NewTextCensor(aliyun.Config{
    AccessKeyID:     "...",
    AccessKeySecret: "...",
    Endpoint:        "green-cip.cn-shanghai.aliyuncs.com",
})
result, err := c.CensorText(ctx, text)

腾讯云

import qcloud "github.com/LingByte/ling-base/providers/censor/qcloud"

c, err := qcloud.NewTextCensor(qcloud.Config{
    SecretID:  "...",
    SecretKey: "...",
    Region:    "ap-guangzhou",
    BizType:   "default",
})

图片审核(同步)

import qcloud "github.com/LingByte/ling-base/providers/censor/qcloud"

c, _ := qcloud.NewImageCensor(qcloud.Config{
    SecretID:  "...",
    SecretKey: "...",
    Region:    "ap-guangzhou",
})

// 传入可公网访问的图片 URL
result, err := c.CensorImage(ctx, "https://cdn.example.com/user-upload.jpg")

音频/视频审核(异步)

import (
    "time"
    "github.com/LingByte/ling-base/providers/censor"
    aliyun "github.com/LingByte/ling-base/providers/censor/aliyun"
)

c, _ := aliyun.NewVideoCensor(aliyun.Config{
    AccessKeyID:     "...",
    AccessKeySecret: "...",
})

taskID, err := c.SubmitCensorVideo(ctx, "https://cdn.example.com/video.mp4")
if err != nil {
    panic(err)
}

for {
    snap, err := c.GetCensorResult(ctx, taskID)
    if err != nil {
        panic(err)
    }
    switch snap.Status {
    case censor.JobFinished:
        fmt.Println(snap.Suggestion, snap.Label, snap.Score)
        return
    case censor.JobFailed:
        panic(snap.Error)
    case censor.JobWaiting, censor.JobDoing:
        time.Sleep(5 * time.Second)
    }
}

生产环境应对轮询加指数退避与总超时。

业务集成:发帖前审核

func publishPost(ctx context.Context, text, imageURL string) error {
    textResult, err := textCensor.CensorText(ctx, text)
    if err != nil {
        return err
    }
    if textResult.Suggestion == censor.SuggestionBlock {
        return ErrContentBlocked
    }

    if imageURL != "" {
        imgResult, err := imageCensor.CensorImage(ctx, imageURL)
        if err != nil {
            return err
        }
        if imgResult.Suggestion != censor.SuggestionPass {
            return ErrContentReview
        }
    }
    return savePost(text, imageURL)
}

Provider 配置参考

七牛 qiniu.Config

字段说明默认
AccessKey七牛 AK必填
SecretKey七牛 SK必填
HostAPI 主机ai.qiniuapi.com

阿里云 aliyun.Config

字段说明默认
AccessKeyID / AccessKeySecret阿里云凭证必填
EndpointGreen 接入点green-cip.cn-shanghai.aliyuncs.com

腾讯云 qcloud.Config

字段说明默认
SecretID / SecretKey腾讯云凭证必填
Region地域ap-guangzhou
BizType业务类型default

辅助函数

msg := censor.BuildCensorMsg(censor.LabelPorn) // "pornographic content"

测试

cd providers/censor && go test -cover
cd providers/censor/qiniu && go test -cover
cd providers/censor/aliyun && go test -cover
cd providers/censor/qcloud && go test -cover

On this page