diff --git a/ci_media.go b/ci_media.go index 48b572a..d59ec0e 100644 --- a/ci_media.go +++ b/ci_media.go @@ -3,6 +3,7 @@ package cos import ( "context" "encoding/xml" + "fmt" "net/http" ) @@ -506,6 +507,7 @@ type MediaProcessBucket struct { CreateTime string `xml:"CreateTime,omitempty"` } +// 媒体bucket接口 https://cloud.tencent.com/document/product/436/48988 func (s *CIService) DescribeMediaProcessBuckets(ctx context.Context, opt *DescribeMediaProcessBucketsOptions) (*DescribeMediaProcessBucketsResult, *Response, error) { var res DescribeMediaProcessBucketsResult sendOpt := sendOptions{ @@ -518,3 +520,123 @@ func (s *CIService) DescribeMediaProcessBuckets(ctx context.Context, opt *Descri resp, err := s.client.send(ctx, &sendOpt) return &res, resp, err } + +type GetMediaInfoResult struct { + XMLName xml.Name `xml:"Response"` + MediaInfo struct { + Format struct { + Bitrate float32 `xml:"Bitrate"` + Duration float32 `xml:"Duration"` + FormatLongName string `xml:"FormatLongName"` + FormatName string `xml:"FormatName"` + NumProgram int `xml:"NumProgram"` + NumStream int `xml:"NumStream"` + Size int `xml:"Size"` + StartTime float32 `xml:"StartTime"` + } `xml:"Format"` + Stream struct { + Audio []struct { + Index int `xml:"Index"` + CodecName string `xml:"CodecName"` + CodecLongName string `xml:"CodecLongName"` + CodecTimeBase string `xml:"CodecTimeBase"` + CodecTagString string `xml:"CodecTagString"` + CodecTag string `xml:"CodecTag"` + SampleFmt string `xml:"SampleFmt"` + SampleRate int `xml:"SampleRate"` + Channel int `xml:"Channel"` + ChannelLayout string `xml:"ChannelLayout"` + Timebase string `xml:"Timebase"` + StartTime float32 `xml:"StartTime"` + Duration float32 `xml:"Duration"` + Bitrate float32 `xml:"Bitrate"` + Language string `xml:"Language"` + } `xml:"Audio"` + Subtitle struct { + Index int `xml:"Index"` + Language string `xml:"Language"` + } `xml:"Subtitle"` + Video struct { + Index int `xml:"Index"` + CodecName string `xml:"CodecName"` + CodecLongName string `xml:"CodecLongName"` + CodecTimeBase string `xml:"CodecTimeBase"` + CodecTagString string `xml:"CodecTagString"` + CodecTag string `xml:"CodecTag"` + Profile string `xml:"Profile"` + Height int `xml:"Height"` + Width int `xml:"Width"` + HasBFrame int `xml:"HasBFrame"` + RefFrames int `xml:"RefFrames"` + Sar string `xml:"Sar"` + Dar string `xml:"Dar"` + PixFormat string `xml:"PixFormat"` + FieldOrder string `xml:"FieldOrder"` + Level int `xml:"Level"` + Fps float32 `xml:"Fps"` + AvgFps string `xml:"AvgFps"` + Timebase string `xml:"Timebase"` + StartTime float32 `xml:"StartTime"` + Duration float32 `xml:"Duration"` + Bitrate float32 `xml:"Bitrate"` + NumFrames int `xml:"NumFrames"` + Language string `xml:"Language"` + } `xml:"Video"` + } `xml:"Stream"` + } `xml:"MediaInfo"` +} + +// 媒体信息接口 https://cloud.tencent.com/document/product/436/55672 +func (s *CIService) GetMediaInfo(ctx context.Context, name string, opt *ObjectGetOptions, id ...string) (*GetMediaInfoResult, *Response, error) { + var u string + if len(id) == 1 { + u = fmt.Sprintf("/%s?versionId=%s&ci-process=videoinfo", encodeURIComponent(name), id[0]) + } else if len(id) == 0 { + u = fmt.Sprintf("/%s?ci-process=videoinfo", encodeURIComponent(name)) + } else { + return nil, nil, fmt.Errorf("wrong params") + } + + var res GetMediaInfoResult + sendOpt := sendOptions{ + baseURL: s.client.BaseURL.BucketURL, + uri: u, + method: http.MethodGet, + optQuery: opt, + optHeader: opt, + result: &res, + } + resp, err := s.client.send(ctx, &sendOpt) + return &res, resp, err +} + +type GetSnapshotOptions struct { + Time float32 `url:"time,omitempty"` + Height int `url:"height,omitempty"` + Width int `url:"width,omitempty"` + Format string `url:"format,omitempty"` + Rotate string `url:"rotate,omitempty"` + Mode string `url:"mode,omitempty"` +} + +// 媒体截图接口 https://cloud.tencent.com/document/product/436/55671 +func (s *CIService) GetSnapshot(ctx context.Context, name string, opt *GetSnapshotOptions, id ...string) (*Response, error) { + var u string + if len(id) == 1 { + u = fmt.Sprintf("/%s?versionId=%s&ci-process=snapshot", encodeURIComponent(name), id[0]) + } else if len(id) == 0 { + u = fmt.Sprintf("/%s?ci-process=snapshot", encodeURIComponent(name)) + } else { + return nil, fmt.Errorf("wrong params") + } + + sendOpt := sendOptions{ + baseURL: s.client.BaseURL.BucketURL, + uri: u, + method: http.MethodGet, + optQuery: opt, + disableCloseBody: true, + } + resp, err := s.client.send(ctx, &sendOpt) + return resp, err +} diff --git a/example/CI/media_process/describe_media_buckets.go b/example/CI/media_process/describe_media_buckets.go new file mode 100644 index 0000000..5ef487f --- /dev/null +++ b/example/CI/media_process/describe_media_buckets.go @@ -0,0 +1,58 @@ +package main + +import ( + "context" + "fmt" + "net/http" + "net/url" + "os" + + "github.com/tencentyun/cos-go-sdk-v5" + "github.com/tencentyun/cos-go-sdk-v5/debug" +) + +func log_status(err error) { + if err == nil { + return + } + if cos.IsNotFoundError(err) { + // WARN + fmt.Println("WARN: Resource is not existed") + } else if e, ok := cos.IsCOSError(err); ok { + fmt.Printf("ERROR: Code: %v\n", e.Code) + fmt.Printf("ERROR: Message: %v\n", e.Message) + fmt.Printf("ERROR: Resource: %v\n", e.Resource) + fmt.Printf("ERROR: RequestId: %v\n", e.RequestID) + // ERROR + } else { + fmt.Printf("ERROR: %v\n", err) + // ERROR + } +} + +func main() { + u, _ := url.Parse("https://test-1259654469.cos.ap-guangzhou.myqcloud.com") + // DescirbeMediaBuckets 需要设置 CIURL 为 ci..myqcloud.com + cu, _ := url.Parse("https://ci.ap-guangzhou.myqcloud.com") + b := &cos.BaseURL{BucketURL: u, CIURL: cu} + c := cos.NewClient(b, &http.Client{ + Transport: &cos.AuthorizationTransport{ + SecretID: os.Getenv("COS_SECRETID"), + SecretKey: os.Getenv("COS_SECRETKEY"), + Transport: &debug.DebugRequestTransport{ + RequestHeader: true, + // Notice when put a large file and set need the request body, might happend out of memory error. + RequestBody: true, + ResponseHeader: true, + ResponseBody: true, + }, + }, + }) + + opt := &cos.DescribeMediaProcessBucketsOptions{ + Regions: "ap-guangzhou", + } + res, _, err := c.CI.DescribeMediaProcessBuckets(context.Background(), opt) + log_status(err) + fmt.Printf("res: %+v\n", res) +} diff --git a/example/CI/media_process/get_media_info.go b/example/CI/media_process/get_media_info.go new file mode 100644 index 0000000..edabea2 --- /dev/null +++ b/example/CI/media_process/get_media_info.go @@ -0,0 +1,53 @@ +package main + +import ( + "context" + "fmt" + "net/http" + "net/url" + "os" + + "github.com/tencentyun/cos-go-sdk-v5" + "github.com/tencentyun/cos-go-sdk-v5/debug" +) + +func log_status(err error) { + if err == nil { + return + } + if cos.IsNotFoundError(err) { + // WARN + fmt.Println("WARN: Resource is not existed") + } else if e, ok := cos.IsCOSError(err); ok { + fmt.Printf("ERROR: Code: %v\n", e.Code) + fmt.Printf("ERROR: Message: %v\n", e.Message) + fmt.Printf("ERROR: Resource: %v\n", e.Resource) + fmt.Printf("ERROR: RequestId: %v\n", e.RequestID) + // ERROR + } else { + fmt.Printf("ERROR: %v\n", err) + // ERROR + } +} + +func main() { + u, _ := url.Parse("https://test-1259654469.cos.ap-guangzhou.myqcloud.com") + b := &cos.BaseURL{BucketURL: u} + c := cos.NewClient(b, &http.Client{ + Transport: &cos.AuthorizationTransport{ + SecretID: os.Getenv("COS_SECRETID"), + SecretKey: os.Getenv("COS_SECRETKEY"), + Transport: &debug.DebugRequestTransport{ + RequestHeader: true, + // Notice when put a large file and set need the request body, might happend out of memory error. + RequestBody: true, + ResponseHeader: true, + ResponseBody: true, + }, + }, + }) + + res, _, err := c.CI.GetMediaInfo(context.Background(), "test.mp4", nil) + log_status(err) + fmt.Printf("res: %+v\n", res) +} diff --git a/example/CI/media_process/get_snapshot.go b/example/CI/media_process/get_snapshot.go new file mode 100644 index 0000000..3c9e49f --- /dev/null +++ b/example/CI/media_process/get_snapshot.go @@ -0,0 +1,65 @@ +package main + +import ( + "context" + "fmt" + "io" + "net/http" + "net/url" + "os" + + "github.com/tencentyun/cos-go-sdk-v5" + "github.com/tencentyun/cos-go-sdk-v5/debug" +) + +func log_status(err error) { + if err == nil { + return + } + if cos.IsNotFoundError(err) { + // WARN + fmt.Println("WARN: Resource is not existed") + } else if e, ok := cos.IsCOSError(err); ok { + fmt.Printf("ERROR: Code: %v\n", e.Code) + fmt.Printf("ERROR: Message: %v\n", e.Message) + fmt.Printf("ERROR: Resource: %v\n", e.Resource) + fmt.Printf("ERROR: RequestId: %v\n", e.RequestID) + // ERROR + } else { + fmt.Printf("ERROR: %v\n", err) + // ERROR + } +} + +func main() { + u, _ := url.Parse("https://test-1259654469.cos.ap-guangzhou.myqcloud.com") + b := &cos.BaseURL{BucketURL: u} + c := cos.NewClient(b, &http.Client{ + Transport: &cos.AuthorizationTransport{ + SecretID: os.Getenv("COS_SECRETID"), + SecretKey: os.Getenv("COS_SECRETKEY"), + Transport: &debug.DebugRequestTransport{ + RequestHeader: true, + // Notice when put a large file and set need the request body, might happend out of memory error. + RequestBody: true, + ResponseHeader: true, + ResponseBody: false, + }, + }, + }) + + opt := &cos.GetSnapshotOptions{ + Time: 1, + } + resp, err := c.CI.GetSnapshot(context.Background(), "test.mp4", opt) + log_status(err) + defer resp.Body.Close() + + fd, err := os.OpenFile("test.jpg", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0660) + if err != nil { + log_status(err) + } + _, err = io.Copy(fd, resp.Body) + fd.Close() + log_status(err) +}