|
20 | 20 | from .streambody import StreamBody |
21 | 21 | from .xml2dict import Xml2Dict |
22 | 22 | from .cos_auth import CosS3Auth |
| 23 | +from .cos_auth import CosRtmpAuth |
23 | 24 | from .cos_comm import * |
24 | 25 | from .cos_threadpool import SimpleThreadPool |
25 | 26 | from .cos_exception import CosClientError |
@@ -3625,6 +3626,327 @@ def get_async_fetch_task(self, Bucket, TaskId, **kwargs): |
3625 | 3626 | data = rt.json() |
3626 | 3627 | return data |
3627 | 3628 |
|
| 3629 | + def put_live_channel(self, Bucket, ChannelName, Expire=3600, LiveChannelConfiguration={}, **kwargs): |
| 3630 | + """创建直播通道 |
| 3631 | +
|
| 3632 | + :param Bucket(string): 存储桶名称. |
| 3633 | + :param ChannelName(string): 直播通道名称. |
| 3634 | + :param Expire(int): 推流url签名过期时间. |
| 3635 | + :param LiveChannelConfiguration(dict): 直播通道配置. |
| 3636 | + :param kwargs(dict): 设置请求headers. |
| 3637 | + :return(dict): publish url and playurl. |
| 3638 | +
|
| 3639 | + .. code-block:: python |
| 3640 | + config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象 |
| 3641 | + client = CosS3Client(config) |
| 3642 | + # 设置直播通道配置 |
| 3643 | + livechannel_config = { |
| 3644 | + 'Description': 'channel description', |
| 3645 | + 'Switch': 'Enabled', |
| 3646 | + 'Target': { |
| 3647 | + 'Type': 'HLS', |
| 3648 | + 'FragDuration': '3', |
| 3649 | + 'FragCount': '5', |
| 3650 | + } |
| 3651 | + } |
| 3652 | + response = client.put_live_channel(Bucket='bucket', ChannelName='ch1', LiveChannelConfiguration=livechannel_config) |
| 3653 | + """ |
| 3654 | + xml_config = format_xml(data=LiveChannelConfiguration, root='LiveChannelConfiguration') |
| 3655 | + headers = mapped(kwargs) |
| 3656 | + headers['Content-MD5'] = get_md5(xml_config) |
| 3657 | + headers['Content-Type'] = 'application/xml' |
| 3658 | + params = {'live': ''} |
| 3659 | + url = self._conf.uri(bucket=Bucket, path=ChannelName) |
| 3660 | + logger.info("put live channel, url=:{url} ,headers=:{headers}".format(url=url, headers=headers)) |
| 3661 | + rt = self.send_request( |
| 3662 | + method='PUT', |
| 3663 | + url=url, |
| 3664 | + bucket=Bucket, |
| 3665 | + data=xml_config, |
| 3666 | + auth=CosS3Auth(self._conf, params=params, key=ChannelName), |
| 3667 | + headers=headers, |
| 3668 | + params=params) |
| 3669 | + data = xml_to_dict(rt.content) |
| 3670 | + if data['PublishUrls']['Url'] is not None: |
| 3671 | + rtmpSign = CosRtmpAuth(self._conf, bucket=Bucket, channel=ChannelName, expire=Expire) |
| 3672 | + url = data['PublishUrls']['Url'] |
| 3673 | + url += '?' + rtmpSign.get_rtmp_sign() |
| 3674 | + data['PublishUrls']['Url'] = url |
| 3675 | + return data |
| 3676 | + |
| 3677 | + def get_rtmp_signed_url(self, Bucket, ChannelName, Expire=3600, Params={}): |
| 3678 | + """获取直播通道带签名的推流url |
| 3679 | + :param Bucket(string): 存储桶名称. |
| 3680 | + :param ChannelName(string): 直播通道名称. |
| 3681 | + :return: dict. |
| 3682 | +
|
| 3683 | + .. code-block:: python |
| 3684 | + config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象 |
| 3685 | + client = CosS3Client(config) |
| 3686 | + resp = client.get_rtmp_signed_url(Bucket='bucket', ChannelName='ch1') |
| 3687 | + """ |
| 3688 | + rtmp_signed_url = 'rtmp://{bucket}.cos.{region}.myqcloud.com/live/{channel}'.format(bucket=Bucket, region=self._conf._region, channel=ChannelName) |
| 3689 | + rtmpAuth = CosRtmpAuth(self._conf, bucket=Bucket, channel=ChannelName, params = Params, expire=Expire) |
| 3690 | + return rtmp_signed_url + '?' + rtmpAuth.get_rtmp_sign() |
| 3691 | + |
| 3692 | + def get_live_channel_info(self, Bucket, ChannelName, **kwargs): |
| 3693 | + """获取直播通道配置信息 |
| 3694 | +
|
| 3695 | + :param Bucket(string): 存储桶名称. |
| 3696 | + :param ChannelName(string): 直播通道名称. |
| 3697 | + :param kwargs(dict): 设置请求headers. |
| 3698 | + :return: dict. |
| 3699 | +
|
| 3700 | + .. code-block:: python |
| 3701 | + config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象 |
| 3702 | + client = CosS3Client(config) |
| 3703 | + resp = client.get_live_channel_info(Bucket='bucket', ChannelName='ch1') |
| 3704 | + """ |
| 3705 | + params = {'live': ''} |
| 3706 | + headers = mapped(kwargs) |
| 3707 | + url = self._conf.uri(bucket=Bucket, path=ChannelName) |
| 3708 | + logger.info("get live channel info, url=:{url} ,headers=:{headers}".format(url=url, headers=headers)) |
| 3709 | + rt = self.send_request( |
| 3710 | + method='GET', |
| 3711 | + url=url, |
| 3712 | + bucket=Bucket, |
| 3713 | + auth=CosS3Auth(self._conf, params=params, key=ChannelName), |
| 3714 | + headers=headers, |
| 3715 | + params=params) |
| 3716 | + data = xml_to_dict(rt.content) |
| 3717 | + return data |
| 3718 | + |
| 3719 | + def put_live_channel_switch(self, Bucket, ChannelName, Switch, **kwargs): |
| 3720 | + """禁用或者开启直播通道 |
| 3721 | +
|
| 3722 | + :param Bucket(string): 存储桶名称. |
| 3723 | + :param ChannelName(string): 直播通道名称. |
| 3724 | + :param Switch(string): 'enabled'或'disabled'. |
| 3725 | + :param kwargs(dict): 设置请求headers. |
| 3726 | + :return(None). |
| 3727 | +
|
| 3728 | + .. code-block:: python |
| 3729 | + config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象 |
| 3730 | + client = CosS3Client(config) |
| 3731 | + client.put_live_channel_switch(Bucket='bucket', ChannelName='ch1', Switch='enabled') |
| 3732 | + """ |
| 3733 | + params = {'live': ''} |
| 3734 | + if Switch in ['enabled', 'disabled']: |
| 3735 | + params['switch'] = Switch |
| 3736 | + else: |
| 3737 | + raise CosClientError('switch must be enabled or disabled') |
| 3738 | + |
| 3739 | + headers = mapped(kwargs) |
| 3740 | + url = self._conf.uri(bucket=Bucket, path=ChannelName) |
| 3741 | + logger.info("put live channel switch, url=:{url} ,headers=:{headers}".format(url=url, headers=headers)) |
| 3742 | + self.send_request( |
| 3743 | + method='PUT', |
| 3744 | + url=url, |
| 3745 | + bucket=Bucket, |
| 3746 | + auth=CosS3Auth(self._conf, params=params, key=ChannelName), |
| 3747 | + headers=headers, |
| 3748 | + params=params) |
| 3749 | + return None |
| 3750 | + |
| 3751 | + def get_live_channel_history(self, Bucket, ChannelName, **kwargs): |
| 3752 | + """获取直播通道推流历史 |
| 3753 | +
|
| 3754 | + :param Bucket(string): 存储桶名称. |
| 3755 | + :param ChannelName(string): 直播通道名称. |
| 3756 | + :param kwargs(dict): 设置请求headers. |
| 3757 | + :return(dict). |
| 3758 | +
|
| 3759 | + .. code-block:: python |
| 3760 | + config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象 |
| 3761 | + client = CosS3Client(config) |
| 3762 | + resp = client.get_live_channel_history(Bucket='bucket', ChannelName='ch1') |
| 3763 | + """ |
| 3764 | + params = {'live': '', 'comp' : 'history'} |
| 3765 | + headers = mapped(kwargs) |
| 3766 | + url = self._conf.uri(bucket=Bucket, path=ChannelName) |
| 3767 | + logger.info("get live channel history, url=:{url} ,headers=:{headers}".format(url=url, headers=headers)) |
| 3768 | + rt = self.send_request( |
| 3769 | + method='GET', |
| 3770 | + url=url, |
| 3771 | + bucket=Bucket, |
| 3772 | + auth=CosS3Auth(self._conf, params=params, key=ChannelName), |
| 3773 | + headers=headers, |
| 3774 | + params=params) |
| 3775 | + data = xml_to_dict(rt.content) |
| 3776 | + format_dict(data, ['LiveRecord']) |
| 3777 | + return data |
| 3778 | + |
| 3779 | + def get_live_channel_status(self, Bucket, ChannelName, **kwargs): |
| 3780 | + """获取直播通道推流状态 |
| 3781 | +
|
| 3782 | + :param Bucket(string): 存储桶名称. |
| 3783 | + :param ChannelName(string): 直播通道名称. |
| 3784 | + :param kwargs(dict): 设置请求headers. |
| 3785 | + :return(dict). |
| 3786 | +
|
| 3787 | + .. code-block:: python |
| 3788 | + config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象 |
| 3789 | + client = CosS3Client(config) |
| 3790 | + resp = client.get_live_channel_status(Bucket='bucket', ChannelName='ch1') |
| 3791 | + """ |
| 3792 | + params = {'live': '', 'comp' : 'status'} |
| 3793 | + headers = mapped(kwargs) |
| 3794 | + url = self._conf.uri(bucket=Bucket, path=ChannelName) |
| 3795 | + logger.info("get live channel status, url=:{url} ,headers=:{headers}".format(url=url, headers=headers)) |
| 3796 | + rt = self.send_request( |
| 3797 | + method='GET', |
| 3798 | + url=url, |
| 3799 | + bucket=Bucket, |
| 3800 | + auth=CosS3Auth(self._conf, params=params, key=ChannelName), |
| 3801 | + headers=headers, |
| 3802 | + params=params) |
| 3803 | + data = xml_to_dict(rt.content) |
| 3804 | + return data |
| 3805 | + |
| 3806 | + def delete_live_channel(self, Bucket, ChannelName, **kwargs): |
| 3807 | + """删除直播通道 |
| 3808 | +
|
| 3809 | + :param Bucket(string): 存储桶名称. |
| 3810 | + :param ChannelName(string): 直播通道名称. |
| 3811 | + :param kwargs(dict): 设置请求headers. |
| 3812 | + :return(dict). |
| 3813 | +
|
| 3814 | + .. code-block:: python |
| 3815 | + config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象 |
| 3816 | + client = CosS3Client(config) |
| 3817 | + client.delete_live_channel(Bucket='bucket', ChannelName='ch1') |
| 3818 | + """ |
| 3819 | + params = {'live': ''} |
| 3820 | + url = self._conf.uri(bucket=Bucket, path=ChannelName) |
| 3821 | + headers = mapped(kwargs) |
| 3822 | + logger.info("delete live channel, url=:{url} ,headers=:{headers}".format(url=url, headers=headers)) |
| 3823 | + rt = self.send_request( |
| 3824 | + method='DELETE', |
| 3825 | + url=url, |
| 3826 | + bucket=Bucket, |
| 3827 | + auth=CosS3Auth(self._conf, params=params, key=ChannelName), |
| 3828 | + headers=headers, |
| 3829 | + params=params) |
| 3830 | + data = dict(**rt.headers) |
| 3831 | + return data |
| 3832 | + |
| 3833 | + def get_vod_playlist(self, Bucket, ChannelName, StartTime = 0, EndTime = 0, **kwargs): |
| 3834 | + """查询指定时间段播放列表文件 |
| 3835 | +
|
| 3836 | + :param Bucket(string): 存储桶名称. |
| 3837 | + :param ChannelName(string): 直播通道名称. |
| 3838 | + :param StartTime(int): 播放列表ts文件的起始时间,格式为unix时间戳. |
| 3839 | + :param EndTime(int): 播放列表ts文件的结束时间,格式为unix时间戳. |
| 3840 | + :param kwargs(dict): 设置请求headers. |
| 3841 | + :return(string). |
| 3842 | +
|
| 3843 | + .. code-block:: python |
| 3844 | + config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象 |
| 3845 | + client = CosS3Client(config) |
| 3846 | + resp = client.get_vod_playlist(Bucket='bucket', ChannelName='ch1', StartTime=1611218201, EndTime=1611218300) |
| 3847 | + """ |
| 3848 | + if StartTime <= 0 or EndTime <= 0: |
| 3849 | + raise CosClientError('invalid timestamp') |
| 3850 | + if StartTime >= EndTime: |
| 3851 | + raise CosClientError('StartTime must be less than EndTime') |
| 3852 | + |
| 3853 | + params = {'vod': '', 'starttime' : StartTime, 'endtime' : EndTime} |
| 3854 | + headers = mapped(kwargs) |
| 3855 | + url = self._conf.uri(bucket=Bucket, path=ChannelName) |
| 3856 | + logger.info("get vod playlist, url=:{url} ,headers=:{headers}".format(url=url, headers=headers)) |
| 3857 | + rt = self.send_request( |
| 3858 | + method='GET', |
| 3859 | + url=url, |
| 3860 | + bucket=Bucket, |
| 3861 | + auth=CosS3Auth(self._conf, params=params, key=ChannelName), |
| 3862 | + headers=headers, |
| 3863 | + params=params) |
| 3864 | + return rt.content |
| 3865 | + |
| 3866 | + def post_vod_playlist(self, Bucket, ChannelName, PlaylistName, StartTime = 0, EndTime = 0, **kwargs): |
| 3867 | + """生成点播播放列表文件 |
| 3868 | +
|
| 3869 | + :param Bucket(string): 存储桶名称. |
| 3870 | + :param ChannelName(string): 直播通道名称. |
| 3871 | + :param PlaylistName(string): 播放列表文件名称. |
| 3872 | + :param StartTime(int): 播放列表ts文件的起始时间,格式为unix时间戳. |
| 3873 | + :param EndTime(int): 播放列表ts文件的结束时间,格式为unix时间戳. |
| 3874 | + :param kwargs(dict): 设置请求headers. |
| 3875 | + :return(None). |
| 3876 | +
|
| 3877 | + .. code-block:: python |
| 3878 | + config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象 |
| 3879 | + client = CosS3Client(config) |
| 3880 | + resp = client.post_vod_playlist(Bucket='bucket', ChannelName='ch1', PlaylistName='test.m3u8', StartTime=1611218201, EndTime=1611218300) |
| 3881 | + """ |
| 3882 | + if StartTime <= 0 or EndTime <= 0: |
| 3883 | + raise CosClientError('invalid timestamp') |
| 3884 | + if StartTime >= EndTime: |
| 3885 | + raise CosClientError('StartTime must be less than EndTime') |
| 3886 | + if not PlaylistName.endswith('.m3u8'): |
| 3887 | + raise CosClientError('PlaylistName must be end with .m3u8') |
| 3888 | + |
| 3889 | + params = {'vod': '', 'starttime' : StartTime, 'endtime' : EndTime} |
| 3890 | + headers = mapped(kwargs) |
| 3891 | + file_path = ChannelName + '/' + PlaylistName |
| 3892 | + url = self._conf.uri(bucket=Bucket, path=file_path) |
| 3893 | + logger.info("post vod playlist, url=:{url} ,headers=:{headers}".format(url=url, headers=headers)) |
| 3894 | + rt = self.send_request( |
| 3895 | + method='POST', |
| 3896 | + url=url, |
| 3897 | + bucket=Bucket, |
| 3898 | + auth=CosS3Auth(self._conf, params=params, key=file_path), |
| 3899 | + headers=headers, |
| 3900 | + params=params) |
| 3901 | + return None |
| 3902 | + |
| 3903 | + def list_live_channel(self, Bucket, MaxKeys = 100, Prefix = '', Marker = '', **kwargs): |
| 3904 | + """获取直播通道列表 |
| 3905 | +
|
| 3906 | + :param Bucket(string): 存储桶名称. |
| 3907 | + :param MaxKeys(int): 每页可以列出通道数量的最大值,有效值范围为[1, 1000],默认值:100. |
| 3908 | + :param Prefix(string): 限定返回的 LiveChannel 必须以 prefix 作为前缀. |
| 3909 | + :param Marker(string): 从 marker 之后按字母排序的第一个开始返回. |
| 3910 | + :param kwargs(dict): 设置请求headers. |
| 3911 | + :return: string. |
| 3912 | +
|
| 3913 | + .. code-block:: python |
| 3914 | + config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象 |
| 3915 | + client = CosS3Client(config) |
| 3916 | + resp = client.list_channel(Bucket='bucket', MaxKeys=100) |
| 3917 | + """ |
| 3918 | + params = {'live' : ''} |
| 3919 | + if MaxKeys >= 1: |
| 3920 | + params['max-keys'] = MaxKeys |
| 3921 | + if Prefix != '': |
| 3922 | + params['prefix'] = Prefix |
| 3923 | + if Marker != '': |
| 3924 | + params['marker'] = Marker |
| 3925 | + headers = mapped(kwargs) |
| 3926 | + url = self._conf.uri(bucket=Bucket) |
| 3927 | + logger.info("list live channel, url=:{url} ,headers=:{headers}".format(url=url, headers=headers)) |
| 3928 | + rt = self.send_request( |
| 3929 | + method='GET', |
| 3930 | + url=url, |
| 3931 | + bucket=Bucket, |
| 3932 | + auth=CosS3Auth(self._conf, params=params), |
| 3933 | + headers=headers, |
| 3934 | + params=params) |
| 3935 | + data = xml_to_dict(rt.content) |
| 3936 | + format_dict(data, ['LiveChannel']) |
| 3937 | + decode_result( |
| 3938 | + data, |
| 3939 | + [ |
| 3940 | + 'Prefix', |
| 3941 | + 'Marker', |
| 3942 | + 'MaxKeys', |
| 3943 | + 'IsTruncated', |
| 3944 | + 'NextMarker' |
| 3945 | + ], |
| 3946 | + [ |
| 3947 | + ['LiveChannel', 'Name'], |
| 3948 | + ]) |
| 3949 | + return data |
3628 | 3950 |
|
3629 | 3951 | if __name__ == "__main__": |
3630 | 3952 | pass |
0 commit comments