Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions qcloud_cos/cos_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ def __call__(self, r):
logger.debug("request headers: " + str(r.headers))
return r


class CosRtmpAuth(AuthBase):

def __init__(self, conf, bucket=None, channel=None, params={}, expire=10000):
self._secret_id = conf._secret_id
self._secret_key = conf._secret_key
Expand All @@ -117,8 +119,8 @@ def get_rtmp_sign(self):
sha1.update(to_bytes(rtmp_str))
# get time
sign_time = int(time.time())
sign_time_str = "{start_time};{end_time}".format(start_time = sign_time - 60, end_time = sign_time + self._expire)
str_to_sign = "sha1\n{time}\n{sha1}\n".format(time = sign_time_str, sha1 = sha1.hexdigest())
sign_time_str = "{start_time};{end_time}".format(start_time=sign_time-60, end_time=sign_time+self._expire)
str_to_sign = "sha1\n{time}\n{sha1}\n".format(time=sign_time_str, sha1=sha1.hexdigest())
logger.debug('str_to_sign: ' + str(str_to_sign))
# get sinature
signature = hmac.new(to_bytes(self._secret_key), to_bytes(str_to_sign), hashlib.sha1).hexdigest()
Expand All @@ -130,5 +132,6 @@ def get_rtmp_sign(self):
else:
return rtmp_sign


if __name__ == "__main__":
pass
43 changes: 28 additions & 15 deletions qcloud_cos/cos_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3668,6 +3668,7 @@ def put_live_channel(self, Bucket, ChannelName, Expire=3600, LiveChannelConfigur
:return(dict): publish url and playurl.

.. code-block:: python

config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象
client = CosS3Client(config)
# 设置直播通道配置
Expand Down Expand Up @@ -3699,10 +3700,10 @@ def put_live_channel(self, Bucket, ChannelName, Expire=3600, LiveChannelConfigur
params=params)
data = xml_to_dict(rt.content)
if data['PublishUrls']['Url'] is not None:
rtmpSign = CosRtmpAuth(self._conf, bucket=Bucket, channel=ChannelName, expire=Expire)
url = data['PublishUrls']['Url']
url += '?' + rtmpSign.get_rtmp_sign()
data['PublishUrls']['Url'] = url
rtmpSign = CosRtmpAuth(self._conf, bucket=Bucket, channel=ChannelName, expire=Expire)
url = data['PublishUrls']['Url']
url += '?' + rtmpSign.get_rtmp_sign()
data['PublishUrls']['Url'] = url
return data

def get_rtmp_signed_url(self, Bucket, ChannelName, Expire=3600, Params={}):
Expand All @@ -3712,13 +3713,16 @@ def get_rtmp_signed_url(self, Bucket, ChannelName, Expire=3600, Params={}):
:return: dict.

.. code-block:: python

config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象
client = CosS3Client(config)
resp = client.get_rtmp_signed_url(Bucket='bucket', ChannelName='ch1')
"""
rtmp_signed_url = 'rtmp://{bucket}.cos.{region}.myqcloud.com/live/{channel}'.format(bucket=Bucket, region=self._conf._region, channel=ChannelName)
rtmpAuth = CosRtmpAuth(self._conf, bucket=Bucket, channel=ChannelName, params = Params, expire=Expire)
return rtmp_signed_url + '?' + rtmpAuth.get_rtmp_sign()
rtmp_signed_url = 'rtmp://{bucket}.cos.{region}.myqcloud.com/live/{channel}'.format(bucket=Bucket,
region=self._conf._region,
channel=ChannelName)
rtmpAuth = CosRtmpAuth(self._conf, bucket=Bucket, channel=ChannelName, params=Params, expire=Expire)
return rtmp_signed_url + '?' + rtmpAuth.get_rtmp_sign()

def get_live_channel_info(self, Bucket, ChannelName, **kwargs):
"""获取直播通道配置信息
Expand All @@ -3729,6 +3733,7 @@ def get_live_channel_info(self, Bucket, ChannelName, **kwargs):
:return: dict.

.. code-block:: python

config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象
client = CosS3Client(config)
resp = client.get_live_channel_info(Bucket='bucket', ChannelName='ch1')
Expand Down Expand Up @@ -3757,6 +3762,7 @@ def put_live_channel_switch(self, Bucket, ChannelName, Switch, **kwargs):
:return(None).

.. code-block:: python

config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象
client = CosS3Client(config)
client.put_live_channel_switch(Bucket='bucket', ChannelName='ch1', Switch='enabled')
Expand Down Expand Up @@ -3788,11 +3794,12 @@ def get_live_channel_history(self, Bucket, ChannelName, **kwargs):
:return(dict).

.. code-block:: python

config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象
client = CosS3Client(config)
resp = client.get_live_channel_history(Bucket='bucket', ChannelName='ch1')
"""
params = {'live': '', 'comp' : 'history'}
params = {'live': '', 'comp': 'history'}
headers = mapped(kwargs)
url = self._conf.uri(bucket=Bucket, path=ChannelName)
logger.info("get live channel history, url=:{url} ,headers=:{headers}".format(url=url, headers=headers))
Expand All @@ -3816,11 +3823,12 @@ def get_live_channel_status(self, Bucket, ChannelName, **kwargs):
:return(dict).

.. code-block:: python

config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象
client = CosS3Client(config)
resp = client.get_live_channel_status(Bucket='bucket', ChannelName='ch1')
"""
params = {'live': '', 'comp' : 'status'}
params = {'live': '', 'comp': 'status'}
headers = mapped(kwargs)
url = self._conf.uri(bucket=Bucket, path=ChannelName)
logger.info("get live channel status, url=:{url} ,headers=:{headers}".format(url=url, headers=headers))
Expand All @@ -3843,6 +3851,7 @@ def delete_live_channel(self, Bucket, ChannelName, **kwargs):
:return(dict).

.. code-block:: python

config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象
client = CosS3Client(config)
client.delete_live_channel(Bucket='bucket', ChannelName='ch1')
Expand All @@ -3861,7 +3870,7 @@ def delete_live_channel(self, Bucket, ChannelName, **kwargs):
data = dict(**rt.headers)
return data

def get_vod_playlist(self, Bucket, ChannelName, StartTime = 0, EndTime = 0, **kwargs):
def get_vod_playlist(self, Bucket, ChannelName, StartTime=0, EndTime=0, **kwargs):
"""查询指定时间段播放列表文件

:param Bucket(string): 存储桶名称.
Expand All @@ -3872,6 +3881,7 @@ def get_vod_playlist(self, Bucket, ChannelName, StartTime = 0, EndTime = 0, **kw
:return(string).

.. code-block:: python

config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象
client = CosS3Client(config)
resp = client.get_vod_playlist(Bucket='bucket', ChannelName='ch1', StartTime=1611218201, EndTime=1611218300)
Expand All @@ -3881,7 +3891,7 @@ def get_vod_playlist(self, Bucket, ChannelName, StartTime = 0, EndTime = 0, **kw
if StartTime >= EndTime:
raise CosClientError('StartTime must be less than EndTime')

params = {'vod': '', 'starttime' : StartTime, 'endtime' : EndTime}
params = {'vod': '', 'starttime': StartTime, 'endtime': EndTime}
headers = mapped(kwargs)
url = self._conf.uri(bucket=Bucket, path=ChannelName)
logger.info("get vod playlist, url=:{url} ,headers=:{headers}".format(url=url, headers=headers))
Expand All @@ -3894,7 +3904,7 @@ def get_vod_playlist(self, Bucket, ChannelName, StartTime = 0, EndTime = 0, **kw
params=params)
return rt.content

def post_vod_playlist(self, Bucket, ChannelName, PlaylistName, StartTime = 0, EndTime = 0, **kwargs):
def post_vod_playlist(self, Bucket, ChannelName, PlaylistName, StartTime=0, EndTime=0, **kwargs):
"""生成点播播放列表文件

:param Bucket(string): 存储桶名称.
Expand All @@ -3906,6 +3916,7 @@ def post_vod_playlist(self, Bucket, ChannelName, PlaylistName, StartTime = 0, En
:return(None).

.. code-block:: python

config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象
client = CosS3Client(config)
resp = client.post_vod_playlist(Bucket='bucket', ChannelName='ch1', PlaylistName='test.m3u8', StartTime=1611218201, EndTime=1611218300)
Expand All @@ -3917,7 +3928,7 @@ def post_vod_playlist(self, Bucket, ChannelName, PlaylistName, StartTime = 0, En
if not PlaylistName.endswith('.m3u8'):
raise CosClientError('PlaylistName must be end with .m3u8')

params = {'vod': '', 'starttime' : StartTime, 'endtime' : EndTime}
params = {'vod': '', 'starttime': StartTime, 'endtime': EndTime}
headers = mapped(kwargs)
file_path = ChannelName + '/' + PlaylistName
url = self._conf.uri(bucket=Bucket, path=file_path)
Expand All @@ -3931,7 +3942,7 @@ def post_vod_playlist(self, Bucket, ChannelName, PlaylistName, StartTime = 0, En
params=params)
return None

def list_live_channel(self, Bucket, MaxKeys = 100, Prefix = '', Marker = '', **kwargs):
def list_live_channel(self, Bucket, MaxKeys=100, Prefix='', Marker='', **kwargs):
"""获取直播通道列表

:param Bucket(string): 存储桶名称.
Expand All @@ -3942,11 +3953,12 @@ def list_live_channel(self, Bucket, MaxKeys = 100, Prefix = '', Marker = '', **k
:return: string.

.. code-block:: python

config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象
client = CosS3Client(config)
resp = client.list_channel(Bucket='bucket', MaxKeys=100)
"""
params = {'live' : ''}
params = {'live': ''}
if MaxKeys >= 1:
params['max-keys'] = MaxKeys
if Prefix != '':
Expand Down Expand Up @@ -3979,5 +3991,6 @@ def list_live_channel(self, Bucket, MaxKeys = 100, Prefix = '', Marker = '', **k
])
return data


if __name__ == "__main__":
pass
108 changes: 55 additions & 53 deletions ut/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1358,7 +1358,7 @@ def test_rsa_client():


def test_live_channel():
print ("create live channel...")
"""测试rtmp推流功能"""
livechannel_config = {
'Description': 'cos python sdk test',
'Switch': 'Enabled',
Expand All @@ -1372,36 +1372,35 @@ def test_live_channel():

try:
response = client.put_live_channel(
Bucket = test_bucket,
ChannelName = channel_name,
LiveChannelConfiguration = livechannel_config)
assert(response)
print(response)
Bucket=test_bucket,
ChannelName=channel_name,
LiveChannelConfiguration=livechannel_config)
assert (response)
except Exception as e:
if e.get_error_code() != 'ChannelStillLive':
return

print ("get live channel info...")
print("get live channel info...")
response = client.get_live_channel_info(
Bucket = test_bucket,
ChannelName = channel_name)
Bucket=test_bucket,
ChannelName=channel_name)
print(response)
assert(response['Switch'] == 'Enabled')
assert(response['Description'] == 'cos python sdk test')
assert(response['Target']['Type'] == 'HLS')
assert(response['Target']['FragDuration'] == '3')
assert(response['Target']['FragCount'] == '5')
assert(response['Target']['PlaylistName'] == 'playlist.m3u8')

print ("put live channel switch...")
assert (response['Switch'] == 'Enabled')
assert (response['Description'] == 'cos python sdk test')
assert (response['Target']['Type'] == 'HLS')
assert (response['Target']['FragDuration'] == '3')
assert (response['Target']['FragCount'] == '5')
assert (response['Target']['PlaylistName'] == 'playlist.m3u8')

print("put live channel switch...")
client.put_live_channel_switch(
Bucket = test_bucket,
ChannelName = channel_name,
Switch = 'disabled')
Bucket=test_bucket,
ChannelName=channel_name,
Switch='disabled')
response = client.get_live_channel_info(
Bucket=test_bucket,
ChannelName=channel_name)
assert(response['Switch'] == 'Disabled')
assert (response['Switch'] == 'Disabled')
client.put_live_channel_switch(
Bucket=test_bucket,
ChannelName=channel_name,
Expand All @@ -1411,32 +1410,32 @@ def test_live_channel():
ChannelName=channel_name)
assert (response['Switch'] == 'Enabled')

print ("get live channel history...")
print("get live channel history...")
response = client.get_live_channel_history(
Bucket = test_bucket,
ChannelName = channel_name)
Bucket=test_bucket,
ChannelName=channel_name)
print(response)

print ("get live channel status...")
print("get live channel status...")
response = client.get_live_channel_status(
Bucket = test_bucket,
ChannelName = channel_name)
Bucket=test_bucket,
ChannelName=channel_name)
print(response)
assert (response['Status'] == 'Idle' or response['Status'] == 'Live')

print ("list channel...")
print("list channel...")
create_chan_num = 20
for i in range(1, create_chan_num):
ch_name = 'test-list-channel-' + str(i)
client.put_live_channel(
Bucket=test_bucket,
ChannelName=ch_name,
LiveChannelConfiguration=livechannel_config)
response = client.list_live_channel(Bucket = test_bucket, MaxKeys = 10)
response = client.list_live_channel(Bucket=test_bucket, MaxKeys=10)
print(response)
assert (response['MaxKeys'] == '10')
assert (response['IsTruncated'] == 'true')
response = client.list_live_channel(Bucket=test_bucket, MaxKeys=5, Marker = response['NextMarker'])
response = client.list_live_channel(Bucket=test_bucket, MaxKeys=5, Marker=response['NextMarker'])
print(response)
assert (response['MaxKeys'] == '5')
assert (response['IsTruncated'] == 'true')
Expand All @@ -1445,40 +1444,43 @@ def test_live_channel():
ch_name = 'test-list-channel-' + str(i)
client.delete_live_channel(Bucket=test_bucket, ChannelName=ch_name)

print ("post vod playlist")
print("post vod playlist")
'''playlist不以.m3u8结尾'''
try:
client.post_vod_playlist(
Bucket = test_bucket,
ChannelName = channel_name,
PlaylistName = 'test',
StartTime = int(time.time()) - 10000,
EndTime = int(time.time()))
Bucket=test_bucket,
ChannelName=channel_name,
PlaylistName='test',
StartTime=int(time.time()) - 10000,
EndTime=int(time.time()))
except Exception as e:
print e
pass

'''starttime大于endtimne'''
try:
client.post_vod_playlist(
Bucket = test_bucket,
ChannelName = channel_name,
PlaylistName = 'test.m3u8',
StartTime = 10,
EndTime = 9)
Bucket=test_bucket,
ChannelName=channel_name,
PlaylistName='test.m3u8',
StartTime=10,
EndTime=9)
except Exception as e:
print e
pass

client.post_vod_playlist(
Bucket = test_bucket,
ChannelName = channel_name,
PlaylistName = 'test.m3u8',
StartTime = int(time.time()) - 10000,
EndTime = int(time.time()))
Bucket=test_bucket,
ChannelName=channel_name,
PlaylistName='test.m3u8',
StartTime=int(time.time()) - 10000,
EndTime=int(time.time()))
response = client.head_object(
Bucket = test_bucket,
Key = channel_name + '/test.m3u8')
assert(response)
Bucket=test_bucket,
Key=channel_name + '/test.m3u8')
assert (response)

print ("delete live channel...")
print("delete live channel...")
response = client.delete_live_channel(Bucket=test_bucket, ChannelName=channel_name)
assert(response)
assert (response)

if __name__ == "__main__":
setUp()
Expand Down