// 腾讯云直播 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"` }