2023-12-08 23:20:11 +08:00
2023-12-08 23:20:11 +08:00
2023-12-08 23:20:11 +08:00
2023-12-08 23:20:11 +08:00
2023-12-08 23:20:11 +08:00
2023-11-11 05:34:56 +08:00
2023-12-06 00:09:34 +08:00
2023-12-06 18:43:53 +08:00

webp

  • 提供webp生成服务
  • 提供流媒体服务
    • 点击播放之前不加载视频(减少流量消耗)
    • 使用封面图片替代加载视屏第一帧
  • GraphQL 风格API
    • 列表翻页

GraphQL 基本规则

  • 必须指定要求返回的每个字段, 不指定的字段不会被返回, 用于减少无效查询
  • 通过 after before 作为游标翻页, 返回指定id之前或之后的列表, 而不是使用 pageNum, 作用是防止列表变化导致翻页请求结果的部分重复
  • 通过 first last 替代 pageSize 决定选择游标前n个还是游标后的n个列表
// 假设服务器上的数据
const database = {
    users: [
        { id: 1, user_name:'xx1', avatar:'xx1.png', create_time:'2022-01-02 12:12:12' },
        { id: 2, user_name:'xx2', avatar:'xx2.png', create_time:'2022-01-02 12:12:12' },
        { id: 3, user_name:'xx3', avatar:'xx3.png', create_time:'2022-01-02 12:12:12' },
        { id: 4, user_name:'xx4', avatar:'xx4.png', create_time:'2022-01-02 12:12:12' },
    ],
    images: [
        { id: 1, content:'xx1.png', user_id: 1, article_id: 2, text:['xx1'] },
        { id: 2, content:'xx2.png', user_id: 1, article_id: 2, text:['xx2'] },
        { id: 3, content:'xx3.png', user_id: 2, article_id: 4, text:['xx3'] },
        { id: 4, content:'xx4.png', user_id: 2, article_id: 4, text:['xx4'] },
    ]
}
// GET 查询id为1的用户列表, 要求列表中每项只返回 id, 用户名, 头像, 以及符合筛选条件的总数 total
const query = `/api?query={users(id:1){total,list{id,user_name,avatar}}}`
fetch(query).then(res => res.json()).then(data => {
    console.log(data)
    // { data: { users: { total:1, list:[{ id: 1, user_name:'xx1', avatar:'xx1.png' }] } } }
})

// GET 查询 user_id 为 2 的图像列表, 并且包含 user 的部分信息, 以及符合筛选条件的总数 total
const query = `/api?query={images(user_id:2){total,list{id,content,user{id,user_name,avatar}}}}`
fetch(query).then(res => res.json()).then(data => {
    console.log(data)
    /*
    {
        data: {
            images: {
                total:2,
                list:[
                    {id:3,content:'xx3.png',user:{id:2,user_name:'xx2',avatar:'xx2.png'}},
                    {id:4,content:'xx4.png',user:{id:2,user_name:'xx2',avatar:'xx2.png'}},
                ]
            }
        }
    }
    */
})

// GET 查询所有图像的前2个(第一页)
const query = `/api?query={images(first:2){total,list{id,content,user:{id,user_name,avatar}}}}`
fetch(query).then(res => res.json()).then(data => {
    console.log(data)
    /*
    {
        data: {
            images: {
                total:4,
                list:[
                    {id:1,content:'xx1.png',user:{id:1,user_name:'xx1',avatar:'xx1.png'}},
                    {id:2,content:'xx2.png',user:{id:1,user_name:'xx1',avatar:'xx1.png'}},
                ]
            }
        }
    }
    */
})


// GET 查询所有图像的指定id之后的前2个(翻页)
const query = `/api?query={images(after:2,first:2){total,list{id,content,user{id,user_name,avatar}}}}`
fetch(query).then(res => res.json()).then(data => {
    console.log(data)
    /*
    {
        data: {
            images: {
                total:4,
                list:[
                    {id:3,content:'xx3.png',user:{id:2,user_name:'xx2',avatar:'xx2.png'}},
                    {id:4,content:'xx4.png',user:{id:2,user_name:'xx2',avatar:'xx2.png'}},
                ]
            }
        }
    }
    */
})

如何获取schema结构(GraphQL自省)

const query = `/api?query={__schema{types{name,description,fields{name,type{name}}}}}`
const data = await fetch(query).then(res.json())

当前数据结构

type Image struct {
	ID                   int       `json:"id"                      db:"id"`
	Width                int       `json:"width"                   db:"width"`
	Height               int       `json:"height"                  db:"height"`
	Content              string    `json:"content"                 db:"content"`
	Remark               string    `json:"remark"                  db:"remark"`
	Description          string    `json:"description"             db:"description"`
	Tags                 string    `json:"tags"                    db:"tags"`
	Rank                 string    `json:"rank"                    db:"rank"`
	CommentNum           int       `json:"comment_num"             db:"comment_num"`
	ArticleCategoryTopId int       `json:"article_category_top_id" db:"article_category_top_id"`
	PraiseCount          int       `json:"praise_count"            db:"praise_count"`
	CollectCount         int       `json:"collect_count"           db:"collect_count"`
	ArticleID            int       `json:"article_id"              db:"article_id"`
	UserID               int       `json:"user_id"                 db:"user_id"`
	User                 User      `json:"user"                    db:"-"`
	Article              Article   `json:"article"                 db:"-"`
	CreateTime           time.Time `json:"create_time"             db:"create_time"`
	UpdateTime           time.Time `json:"update_time"             db:"update_time"`
	Text                 TextList  `json:"text"                    db:"text"`
}

type TextList []struct {
	Text       string      `json:"text"`
	Confidence float64     `json:"confidence"`
	Coordinate [][]float64 `json:"coordinate"`
}

type User struct {
	ID         int       `json:"id"          db:"id"`
	UserName   *string   `json:"user_name"   db:"user_name"`
	Avatar     *string   `json:"avatar"      db:"avatar"`
	Rank       *string   `json:"rank"        db:"rank"`
	CreateTime time.Time `json:"create_time" db:"create_time"`
	UpdateTime time.Time `json:"update_time" db:"update_time"`
}

type Article struct {
	ID         int       `json:"id"          db:"id"`
	Title      string    `json:"title"       db:"title"`
	Tags       string    `json:"tags"        db:"tags"`
	CreateTime time.Time `json:"create_time" db:"create_time"`
	UpdateTime time.Time `json:"update_time" db:"update_time"`
}
  • 以上为当前基本数据结构和查询方法
  • 如需添加筛选条件排序条件或其他字段后续补充
  • 由于仅为OCR文本搜索提供, 目前图像对象仅支持包含文本搜索的请求 http://www.gameui.net/api?query={images(text:"魔力",after:32128,first:5){list{id,width,height}}}

流媒体

通过流媒体服务降低视频文件加载消耗及防止恶意刷流量 对视频地址添加有效期, 过期需由服务器重新提供token认证观众身份 可后期增加基于用户账户或cookie信任度评估的视频播放权限认证

// 请求视频播放地址
import Hls from 'hls.js'
import axios from 'axios'
axios.get('/video?url=' + encodeURIComponent(this.src)).then(res => {
    const img = res.data.VideoBase.CoverURL
    if (img) {
        video.poster = img
    }
    const m3u8 = res.data.PlayInfoList.PlayInfo.find(x => x.Format === 'm3u8')
    if (!m3u8) {
        video.src = this.src
        return console.log('流媒体地址不含m3u8')
    }
    this.player = new Hls({ maxMaxBufferLength: 5, autoStartLoad: false })
    this.player.loadSource(m3u8.PlayURL)
    this.player.attachMedia(video)
    this.player.on(Hls.Events.MANIFEST_PARSED, () => {
        if (this.autoplay) {
            video.play()
        }
    })
}).catch(err => {
    console.log('未取得流媒体地址')
    video.src = this.src
})
// GET /webp/{type}-{id}-{version}-{width}-{height}-{fit}.{format}
// @type: image avatar article article_attribute ad
// @id: int 图片ID或是文章ID或是广告ID
// @version: update_time 时间戳
// @width: 宽度 1x 2x 3x 倍图直接输入尺寸
// @height: 高度 1x 2x 3x 倍图直接输入尺寸
// @fit: 裁切方式 cover contain fill auto

// GET /img/{type}-{id}.{format}?width=320&height=320&fit=cover
// 更优雅的实现, 使用查询参数的接口 (不幸的是CDN与OSS都不支持)

// endpoint: oss-cn-shanghai-internal.aliyuncs.com

// 获取查询参数
let queryParam = "example query";

// 安全地编码查询参数
let safeParam = encodeURIComponent(queryParam);

// 创建一个带有安全查询参数的URL
let url = "http://example.com/tags?param=" + safeParam;

// 使用fetch API发送请求
fetch(url)
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

Update

# 静态编译
go build bin/main.go

# 上传到服务器
scp ./main root@47.103.40.152:~/main

Dev & Install

# ubuntu 安裝 tesseract-ocr
sudo add-apt-repository ppa:alex-p/tesseract-ocr-devel
sudo apt update
sudo apt install tesseract-ocr
sudo apt install libleptonica-dev
sudo apt install libtesseract-dev

# https://i.scwy.net/code/2020/091108-ocr/
sudo apt install tesseract-ocr
sudo apt install libtesseract-dev
sudo apt install tesseract-ocr-chi-sim

tesseract --list-langs


# 需要安装依赖
sudo apt install libopencv-dev

防止错误 ArucoDetector in namespace cv::aruco does not name a type 將安裝的 opencv 版本從 4.2 更改為 4.7,它工作正常。

# E: 无法定位软件包 libdc1394-22-dev
sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu xenial-security main"
sudo apt update
sudo apt upgrade
sudo apt install libjasper1 libjasper-dev

# 添加主服务器
sudo gedit /etc/apt/sources.list
    deb http://archive.ubuntu.com/ubuntu/ trusty main universe restricted multiverse

sudo apt-get update
sudo apt update
sudo apt upgrade

# GPT 方案
sudo add-apt-repository universe
sudo apt update
sudo apt install libdc1394-22-dev
apt search libdc1394

# 手动下载 https://pkgs.org/download/libdc1394-22
wget http://archive.ubuntu.com/ubuntu/pool/universe/libd/libdc1394-22/libdc1394-22_2.2.5-2.1_amd64.deb
sudo dpkg -i libdc1394-22_2.2.5-2.1_amd64.deb
apt search libdc1394

# 确认安装后注释 Markfile 第52行
cd gocv
make install

# 下载超时请爬墙

torch 模型文件 https://d2j0dndfm35trm.cloudfront.net/resnet-50.t7 https://github.com/facebookarchive/fb.resnet.torch/tree/master/pretrained

Document

通用权重模型接口

获取图片列表(RESTful标准查询)

GET /api/images

{
    page: 1,             // 当前页码
    pageSize: 20,        // 分页数
    next: true,          // 是否存在下一页
    list: [{
        id: 1234,        // 原图ID
        width: 512,      // 原图宽度
        height: 512,     // 原图高度
        user: {          // 来源用户
            id: 1234,
            user_name: 'LAST',
        },
        article: {       // 来源文章
            id: 1234,
            title: 'GAMEX',
        }
    }]
}

列表视图:(输出控制)

Method URL Info Status
GET /api/images 标准顺序查询 ok
GET /api/images?page=1&pageSize=20 指定页码和指定分页大小 ok

筛选规则:(数据过滤)

Method URL Info Statu
GET /api/images?user=1234 筛选指定某用户发表的图片
GET /api/images?choice=1234 筛选指定精选集下的图片
GET /api/images?like=1234 筛选指定用户点赞的图片
GET /api/images?tag=1234 筛选含有指定标签的图片
GET /api/images?tag=1234,1235 筛选含有多个标签之一的图片(并集)
GET /api/images?tag=1234&tag=1235 筛选含有指定多个标签的图片(交集)
GET /api/images?user=1234&tag=123 筛选指定用户的指定标签图片(交集)
GET /api/images?date=20220214+ 时间范围(之后)
GET /api/images?date=20220214- 时间范围(之前)
GET /api/images?date=2022~2023 时间范围(之间)

排序规则:(权重强化)

Method URL Info Status
GET /api/images?similar=1234 根据指定图片的相似图片(指定图片ID) ok
GET /api/images?sort=date+ 排序规则(相似图片查询时此项无效)
GET /api/images?sort=like 根据用户偏好推荐(指定用户的偏好)
GET /api/images?sort=history 根据浏览记录推荐(指定用户的记录)
GET /api/images?sort=choice 根据精选集推荐(指定精选集ID,取一组权重)
  • 注意, 筛选规则为多条件取交集, 单条件的复数取并集
  • 权重强化属于排序规则而非过滤规则

獲取任務列表(標準查询)

GET /api/tasks

{
    page: 1,             // 当前页码
    pageSize: 20,        // 分页数
    next: true,          // 是否存在下一页
    list: [{
        id: 'xxxxxx',    // 任務ID
        type: '',        // 任務類型(推理, 訓練)
        data: {},        // 任務執行數據
        create_time: ''  // 任務創建時間
        update_time: ''  // 任務更新時間
    }],
}

Websocket /api/tasks/{task_id}

{
    // 狀態
    // 進度
    // 結果
}
  • 通過websocket監聽任務狀態變化

模型(我的|共享|熱門|查詢)

圖片(我的|共享|熱門|查詢)

標籤

Description
提供webp生成服务
Readme 7.1 MiB
test Latest
2024-11-04 10:32:37 +08:00
Languages
Go 96.7%
Python 2.2%
Makefile 1.1%