Skip to content

Commit

Permalink
支持边转边播
Browse files Browse the repository at this point in the history
  • Loading branch information
wanjiewu committed Apr 11, 2024
1 parent 9762204 commit 8e69739
Show file tree
Hide file tree
Showing 5 changed files with 495 additions and 40 deletions.
102 changes: 101 additions & 1 deletion ci_media.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ import (
"github.com/mitchellh/mapstructure"
)

type VodInfo struct {
FileId string `xml:"FileId,omitempty"`
SubAppId string `xml:"SubAppId,omitempty"`
}

// JobInput TODO
type JobInput struct {
Object string `xml:"Object,omitempty"`
Expand All @@ -26,7 +31,8 @@ type JobInput struct {
Key string `xml:"Key"`
Value string `xml:"Value"`
} `xml:"CosHeaders"`
Url string `xml:"Url,omitempty"`
Url string `xml:"Url,omitempty"`
Vod *VodInfo `xml:"Vod,omitempty"`
}

// StreamExtract TODO
Expand Down Expand Up @@ -1475,6 +1481,10 @@ func (s *CIService) CreatePlayKey(ctx context.Context) (*PlayKeyResult, *Respons
return &res, resp, err
}

func (s *CIService) CreateMediaPlayKey(ctx context.Context) (*PlayKeyResult, *Response, error) {
return s.CreatePlayKey(ctx)
}

func (s *CIService) GetPlayKey(ctx context.Context) (*PlayKeyResult, *Response, error) {
var res PlayKeyResult
sendOpt := sendOptions{
Expand All @@ -1487,6 +1497,36 @@ func (s *CIService) GetPlayKey(ctx context.Context) (*PlayKeyResult, *Response,
return &res, resp, err
}

func (s *CIService) DescribeMediaPlayKey(ctx context.Context) (*PlayKeyResult, *Response, error) {
var res PlayKeyResult
sendOpt := sendOptions{
baseURL: s.client.BaseURL.CIURL,
uri: "/playKey",
method: http.MethodGet,
result: &res,
}
resp, err := s.client.send(ctx, &sendOpt)
return &res, resp, err
}

type UpdateMediaPlayKeyOptions struct {
MasterPlayKey string `url:"masterPlayKey,omitempty"`
BackupPlayKey string `url:"backupPlayKey,omitempty"`
}

func (s *CIService) UpdateMediaPlayKey(ctx context.Context, opt *UpdateMediaPlayKeyOptions) (*PlayKeyResult, *Response, error) {
var res PlayKeyResult
sendOpt := sendOptions{
baseURL: s.client.BaseURL.CIURL,
uri: "/playKey",
method: http.MethodPut,
optQuery: opt,
result: &res,
}
resp, err := s.client.send(ctx, &sendOpt)
return &res, resp, err
}

// GenerateMediaInfoOptions TODO
type GenerateMediaInfoOptions struct {
XMLName xml.Name `xml:"Request"`
Expand Down Expand Up @@ -3998,3 +4038,63 @@ type ImageOCRTextWordPolygon struct {
Y int `xml:"Y,omitempty"`
} `xml:"RightBottom,omitempty"`
}

type LiveTanscodeVideo struct {
Codec string `xml:"Codec"`
Width string `xml:"Width,omitempty"`
Height string `xml:"Height,omitempty"`
Fps string `xml:"Fps,omitempty"`
Bitrate string `xml:"Bitrate,omitempty"`
Gop string `xml:"Gop,omitempty"`
Maxrate string `xml:"Maxrate,omitempty"`
}

type LiveTanscodeTransConfig struct {
InitialClipNum string `xml:"InitialClipNum,omitempty"`
CosTag string `xml:"CosTag,omitempty"`
HlsEncrypt *HlsEncrypt `xml:"HlsEncrypt,omitempty"`
}

type LiveTanscode struct {
Container *Container `xml:"Container,omitempty"`
Video *LiveTanscodeVideo `xml:"Video,omitempty"`
// TimeInterval *TimeInterval `xml:"TimeInterval,omitempty"`
// Audio *Audio `xml:"Audio,omitempty"`
TransConfig *LiveTanscodeTransConfig `xml:"TransConfig,omitempty"`
}

type GeneratePlayListJobOperation struct {
Tag string `xml:"Tag,omitempty"`
Output *JobOutput `xml:"Output,omitempty"`
MediaResult *MediaResult `xml:"MediaResult,omitempty"`
MediaInfo *MediaInfo `xml:"MediaInfo,omitempty"`
Transcode *LiveTanscode `xml:"Transcode,omitempty"`
UserData string `xml:"UserData,omitempty"`
JobLevel int `xml:"JobLevel,omitempty"`
}

type CreateGeneratePlayListJobOptions struct {
XMLName xml.Name `xml:"Request"`
Tag string `xml:"Tag,omitempty"`
Input *JobInput `xml:"Input,omitempty"`
Operation *GeneratePlayListJobOperation `xml:"Operation,omitempty"`
QueueId string `xml:"QueueId,omitempty"`
QueueType string `xml:"QueueType,omitempty"`
CallBackFormat string `xml:"CallBackFormat,omitempty"`
CallBackType string `xml:"CallBackType,omitempty"`
CallBack string `xml:"CallBack,omitempty"`
CallBackMqConfig *NotifyConfigCallBackMqConfig `xml:"CallBackMqConfig,omitempty"`
}

func (s *CIService) CreateGeneratePlayListJob(ctx context.Context, opt *CreateGeneratePlayListJobOptions) (*CreateJobsResult, *Response, error) {
var res CreateJobsResult
sendOpt := sendOptions{
baseURL: s.client.BaseURL.CIURL,
uri: "/jobs",
method: http.MethodPost,
body: opt,
result: &res,
}
resp, err := s.client.send(ctx, &sendOpt)
return &res, resp, err
}
99 changes: 66 additions & 33 deletions example/CI/media_process/generate_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@ import (
"fmt"
"net/http"
"net/url"
"os"
"time"

"github.com/dgrijalva/jwt-go"
"github.com/tencentyun/cos-go-sdk-v5"
)

type URLToken struct {
SessionToken string `url:"x-cos-security-token,omitempty" header:"-"`
}

type JwtTokens struct {
// base info
Type string `json:"Type"`
Expand All @@ -31,26 +36,23 @@ type JwtTokens struct {
ProtectContentKey int `json:"ProtectContentKey"`
}

// 定义secret
var Secret = []byte("xxx")

func (token JwtTokens) Valid() error {
return nil
}

// 生成jwt
func GenerateToken() (string, error) {
func GenerateToken(appId string, bucketId string, objectKey string, secret []byte) (string, error) {
t := time.Now()
now := t.Unix()
payLoad := JwtTokens{
// 固定为 CosCiToken, 必填参数
Type: "CosCiToken",
// app id,必填参数
AppId: "1234567890",
AppId: appId,
// 播放文件所在的BucketId, 必填参数
BucketId: "test-1234567890",
BucketId: bucketId,
// 播放文件名
Object: "hls_test/no_uri_key.m3u8",
Object: url.QueryEscape(objectKey),
// 固定为client,必填参数
Issuer: "client",
// token颁发时间戳,必填参数
Expand All @@ -70,48 +72,79 @@ func GenerateToken() (string, error) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, payLoad)

//使用指定的secret签名并获得完成的编码后的字符串token
return token.SignedString(Secret)
return token.SignedString(secret)
}

type URLToken struct {
SessionToken string `url:"x-cos-security-token,omitempty" header:"-"`
}
// 验证环境url
func GetCIDomainURL(tak string, tsk string, token *URLToken, appId string, bucketId string, region string, objectKey string, playkey []byte) {
// 固定为getplaylist
name := "getplaylist"

func GetURL() {
// 替换成您的密钥
tak := "xxx"
tsk := "xxx"
token := &URLToken{
SessionToken: "",
}
u, _ := url.Parse("https://" + bucketId + ".ci." + region + ".myqcloud.com")
b := &cos.BaseURL{BucketURL: u}
c := cos.NewClient(b, &http.Client{
Transport: &cos.AuthorizationTransport{
SecretID: tak,
SecretKey: tsk,
SessionToken: token.SessionToken,
},
})
ctx := context.Background()

// 替换成您的桶名称
bucketName := "test-1234567890"
// 替换成您桶所在的region
region := "ap-chongqing"
// 替换成您需要播放的视频名称
objectName := "hls_test/no_uri_key.m3u8"
// 固定为pm3u8
name := "pm3u8"
// 获取预签名
presignedURL, err := c.Object.GetPresignedURL(ctx, http.MethodGet, name, tak, tsk, time.Hour, token)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
// 生成token
generateToken, _ := GenerateToken(appId, bucketId, objectKey, playkey)
resultUrl := presignedURL.String() + "&tokenType=JwtToken&expires=3600&object=" + url.QueryEscape(objectKey) + "&token=" + generateToken
fmt.Println(resultUrl)
}

u, _ := url.Parse("http://" + bucketName + ".ci." + region + ".myqcloud.com")
// cos环境url
func GetCOSDomainURL(tak string, tsk string, token *URLToken, appId string, bucketId string, region string, objectKey string, playkey []byte) {
u, _ := url.Parse("https://" + bucketId + ".cos." + region + ".myqcloud.com")
b := &cos.BaseURL{BucketURL: u}
c := cos.NewClient(b, &http.Client{})
c := cos.NewClient(b, &http.Client{
Transport: &cos.AuthorizationTransport{
SecretID: tak,
SecretKey: tsk,
SessionToken: token.SessionToken,
},
})
ctx := context.Background()

// 获取预签名
presignedURL, err := c.Object.GetPresignedURL(ctx, http.MethodGet, name, tak, tsk, time.Hour, token)
presignedURL, err := c.Object.GetPresignedURL3(ctx, http.MethodGet, objectKey, time.Hour, token)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Println(presignedURL.String())
// 生成token
generateToken, _ := GenerateToken()
resultUrl := presignedURL.String() + "&tokenType=JwtToken&expires=3600&object=" + objectName + "&token=" + generateToken
generateToken, _ := GenerateToken(appId, bucketId, objectKey, playkey)
resultUrl := presignedURL.String() + "&ci-process=pm3u8&expires=43200&&tokenType=JwtToken&token=" + generateToken
fmt.Println(resultUrl)
}

func main() {
GetURL()
// 替换成您的密钥
tak := os.Getenv("COS_SECRETID")
tsk := os.Getenv("COS_SECRETKEY")
token := &URLToken{
SessionToken: "",
}
// 替换成您的桶名称
appId := "1250000000"
// 替换成您的桶名称
bucketId := "test-1250000000"
// 替换成您桶所在的region
region := "ap-chongqing"
// 替换成您需要播放的视频名称
objectKey := "live/a.m3u8"
// 定义secret
var secret = []byte("aaaaaaaaaaa")
GetCIDomainURL(tak, tsk, token, appId, bucketId, region, objectKey, secret)
GetCOSDomainURL(tak, tsk, token, appId, bucketId, region, objectKey, secret)
}
Loading

0 comments on commit 8e69739

Please sign in to comment.