|
|
// 腾讯云直播
|
|
|
package tencent
|
|
|
|
|
|
import (
|
|
|
"crypto/hmac"
|
|
|
"crypto/sha1"
|
|
|
"encoding/base64"
|
|
|
"fmt"
|
|
|
"live/app/common"
|
|
|
"live/app/lib/config"
|
|
|
"log"
|
|
|
"net/url"
|
|
|
"strconv"
|
|
|
"strings"
|
|
|
"time"
|
|
|
)
|
|
|
|
|
|
type live struct {
|
|
|
baseUrl string
|
|
|
pushKey string
|
|
|
pushDomain string
|
|
|
pushExpire int64
|
|
|
pushTreaty string
|
|
|
playKey string
|
|
|
playDomain string
|
|
|
playExpire int64
|
|
|
playTreaty string
|
|
|
playSuffix string
|
|
|
secretId string
|
|
|
secretKey string
|
|
|
expireTime string
|
|
|
}
|
|
|
|
|
|
var Live *live
|
|
|
|
|
|
func init() {
|
|
|
Live = &live{
|
|
|
baseUrl: config.Config.Section("tencent.live").Key("url").String(),
|
|
|
pushKey: config.Config.Section("tencent.live").Key("pushKey").String(),
|
|
|
pushExpire: config.Config.Section("tencent.live").Key("pushExpire").MustInt64(0),
|
|
|
pushDomain: config.Config.Section("tencent.live").Key("pushDomain").String(),
|
|
|
pushTreaty: config.Config.Section("tencent.live").Key("pushTreaty").MustString("rtmp"),
|
|
|
playKey: config.Config.Section("tencent.live").Key("playKey").String(),
|
|
|
playExpire: config.Config.Section("tencent.live").Key("playExpire").MustInt64(0),
|
|
|
playDomain: config.Config.Section("tencent.live").Key("playDomain").String(),
|
|
|
playTreaty: config.Config.Section("tencent.live").Key("playTreaty").MustString("rtmp"),
|
|
|
playSuffix: config.Config.Section("tencent.live").Key("playSuffix").String(),
|
|
|
secretId: config.Config.Section("tencent.live").Key("secretId").String(),
|
|
|
secretKey: config.Config.Section("tencent.live").Key("secretKey").String(),
|
|
|
expireTime: config.Config.Section("tencent.live").Key("expireTime").String(),
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// @Title 获取推流url
|
|
|
func (l *live) GetPushUrl(streamName string, liveItemId uint) string {
|
|
|
streamName = fmt.Sprintf("%s_%v", streamName, liveItemId)
|
|
|
query := ""
|
|
|
if l.pushExpire > 0 {
|
|
|
// 计算超时时间
|
|
|
expTime := time.Now().Add(time.Duration(time.Second.Nanoseconds() * l.pushExpire)).Unix()
|
|
|
|
|
|
// 时间戳转换为大写16进制
|
|
|
txtTime := strings.ToUpper(strconv.FormatInt(expTime, 16))
|
|
|
log.Println(l.pushKey + streamName + txtTime)
|
|
|
txtSecret := common.Md5(l.pushKey + streamName + txtTime)
|
|
|
query = "?" + url.Values{
|
|
|
"txSecret": []string{txtSecret},
|
|
|
"txTime": []string{txtTime},
|
|
|
"liveItemId": []string{strconv.FormatUint(uint64(liveItemId), 10)},
|
|
|
}.Encode()
|
|
|
}
|
|
|
return fmt.Sprintf("%v://%v/live/%v%v", l.pushTreaty, l.pushDomain, streamName, query)
|
|
|
}
|
|
|
|
|
|
// @Title 获取播放url
|
|
|
func (l *live) GetPlayUrl(streamName string, liveItemId uint) string {
|
|
|
streamName = fmt.Sprintf("%s_%v", streamName, liveItemId)
|
|
|
query := ""
|
|
|
if l.playExpire > 0 {
|
|
|
// 计算超时时间
|
|
|
expTime := time.Now().Add(time.Duration(time.Second.Nanoseconds() * l.playExpire)).Unix()
|
|
|
|
|
|
// 时间戳转换为大写16进制
|
|
|
txtTime := strings.ToUpper(strconv.FormatInt(expTime, 16))
|
|
|
log.Println(l.pushKey + streamName + txtTime)
|
|
|
txtSecret := common.Md5(l.playKey + streamName + txtTime)
|
|
|
query = "?" + url.Values{
|
|
|
"txSecret": []string{txtSecret},
|
|
|
"txTime": []string{txtTime},
|
|
|
}.Encode()
|
|
|
}
|
|
|
return fmt.Sprintf("%v://%v/live/%v%v%v", l.playTreaty, l.playDomain, streamName, l.playSuffix, query)
|
|
|
}
|
|
|
|
|
|
// @Title 获取签名
|
|
|
func (l *live) GetSign() string {
|
|
|
signData := url.Values{
|
|
|
"secretId": []string{l.secretId},
|
|
|
"currentTimeStamp": []string{strconv.FormatInt(time.Now().Unix(), 10)},
|
|
|
"expireTime": []string{l.expireTime},
|
|
|
"random": []string{strconv.FormatUint(uint64(Worker.Rander()), 10)},
|
|
|
"oneTimeValid": []string{"1"},
|
|
|
}.Encode()
|
|
|
h := hmac.New(sha1.New, []byte(l.secretKey))
|
|
|
h.Write([]byte(signData))
|
|
|
signTmp := h.Sum(nil)
|
|
|
return base64.StdEncoding.EncodeToString(append(signTmp, []byte(signData)...))
|
|
|
}
|
|
|
|
|
|
// 断流推送数据 文档:https://cloud.tencent.com/document/product/267/20388
|
|
|
type Cutout struct {
|
|
|
App string `json:"app"`
|
|
|
Appid int64 `json:"appid"`
|
|
|
Appname string `json:"appname"`
|
|
|
ChannelID string `json:"channel_id"`
|
|
|
Errcode int64 `json:"errcode"`
|
|
|
Errmsg string `json:"errmsg"`
|
|
|
EventTime int64 `json:"event_time"`
|
|
|
EventType int64 `json:"event_type"` //1=推流 0=断流
|
|
|
Node string `json:"node"`
|
|
|
Sequence string `json:"sequence"`
|
|
|
Sign string `json:"sign"`
|
|
|
StreamID string `json:"stream_id"`
|
|
|
StreamParam string `json:"stream_param"`
|
|
|
T int64 `json:"t"`
|
|
|
UserIP string `json:"user_ip"`
|
|
|
}
|
|
|
|
|
|
// 录制推送数据
|
|
|
type Transcribe struct {
|
|
|
Appid int64 `json:"appid"`
|
|
|
ChannelID string `json:"channel_id"`
|
|
|
Duration int64 `json:"duration"`
|
|
|
EndTime int64 `json:"end_time"`
|
|
|
EventType int64 `json:"event_type"` // 100=直播录制
|
|
|
FileFormat string `json:"file_format"`
|
|
|
FileID string `json:"file_id"`
|
|
|
FileSize int64 `json:"file_size"`
|
|
|
Sign string `json:"sign"`
|
|
|
StartTime int64 `json:"start_time"`
|
|
|
StreamID string `json:"stream_id"`
|
|
|
StreamParam string `json:"stream_param"`
|
|
|
T int64 `json:"t"`
|
|
|
VideoURL string `json:"video_url"`
|
|
|
}
|
|
|
|
|
|
// 截图推送
|
|
|
type ScreenShot struct {
|
|
|
ChannelID string `json:"channel_id"`
|
|
|
CreateTime int64 `json:"create_time"`
|
|
|
EventType int64 `json:"event_type"` // 200=截图推送
|
|
|
FileSize int64 `json:"file_size"`
|
|
|
Height int64 `json:"height"`
|
|
|
PicFullURL string `json:"pic_full_url"`
|
|
|
PicURL string `json:"pic_url"`
|
|
|
Sign string `json:"sign"`
|
|
|
StreamID string `json:"stream_id"`
|
|
|
T int64 `json:"t"`
|
|
|
Width int64 `json:"width"`
|
|
|
}
|
|
|
|
|
|
// 鉴黄推送
|
|
|
type Yello struct {
|
|
|
AbductionRisk []interface{} `json:"abductionRisk"`
|
|
|
App string `json:"app"`
|
|
|
Appid int64 `json:"appid"`
|
|
|
Appname string `json:"appname"`
|
|
|
ChannelID string `json:"channelId"`
|
|
|
Confidence int64 `json:"confidence"`
|
|
|
EventType int64 `json:"event_type"`
|
|
|
FaceDetails []interface{} `json:"faceDetails"`
|
|
|
HotScore int64 `json:"hotScore"`
|
|
|
IllegalScore int64 `json:"illegalScore"`
|
|
|
Img string `json:"img"`
|
|
|
Level int64 `json:"level"`
|
|
|
NormalScore int64 `json:"normalScore"`
|
|
|
OcrMsg string `json:"ocrMsg"`
|
|
|
PolityScore int64 `json:"polityScore"`
|
|
|
PornScore int64 `json:"pornScore"`
|
|
|
ScreenshotTime int64 `json:"screenshotTime"`
|
|
|
SendTime int64 `json:"sendTime"`
|
|
|
SimilarScore int64 `json:"similarScore"`
|
|
|
StreamID string `json:"streamId"`
|
|
|
StreamParam string `json:"stream_param"`
|
|
|
TerrorScore int64 `json:"terrorScore"`
|
|
|
Tid int64 `json:"tid"`
|
|
|
Type []int64 `json:"type"`
|
|
|
}
|
|
|
|
|
|
// 上传视频回调 https://cloud.tencent.com/document/product/266/7830
|
|
|
type Upload struct {
|
|
|
EventType string `json:"EventType"`
|
|
|
FileUploadEvent struct {
|
|
|
FileID string `json:"FileId"`
|
|
|
MediaBasicInfo struct {
|
|
|
ClassID int64 `json:"ClassId"`
|
|
|
ClassName string `json:"ClassName"`
|
|
|
ClassPath string `json:"ClassPath"`
|
|
|
CoverURL string `json:"CoverUrl"`
|
|
|
CreateTime string `json:"CreateTime"`
|
|
|
Description string `json:"Description"`
|
|
|
ExpireTime string `json:"ExpireTime"`
|
|
|
MediaURL string `json:"MediaUrl"`
|
|
|
Name string `json:"Name"`
|
|
|
SourceInfo struct {
|
|
|
SourceContext string `json:"SourceContext"`
|
|
|
SourceType string `json:"SourceType"`
|
|
|
} `json:"SourceInfo"`
|
|
|
StorageRegion string `json:"StorageRegion"`
|
|
|
TagSet []interface{} `json:"TagSet"`
|
|
|
Type string `json:"Type"`
|
|
|
UpdateTime string `json:"UpdateTime"`
|
|
|
Vid string `json:"Vid"`
|
|
|
} `json:"MediaBasicInfo"`
|
|
|
ProcedureTaskID string `json:"ProcedureTaskId"`
|
|
|
} `json:"FileUploadEvent"`
|
|
|
}
|