From 546ae402f34c8b2ba7739d7b613400b8381ca6ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B8=A3=E9=95=9D?= Date: Fri, 12 Aug 2016 16:44:13 +0800 Subject: [PATCH 1/2] rtmp --- oss2/api.py | 6 +-- oss2/models.py | 39 +++++++++++------ oss2/xml_utils.py | 13 +++--- tests/test_mock_bucket.py | 91 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 123 insertions(+), 26 deletions(-) diff --git a/oss2/api.py b/oss2/api.py index 4bd3a40f..59e3cb6c 100644 --- a/oss2/api.py +++ b/oss2/api.py @@ -93,7 +93,7 @@ def progress_callback(bytes_consumed, total_bytes): `http_date` 函数把Unix Time转换为HTTP Date;而 `http_to_unixtime` 则做相反的转换。如 :: >>> import oss2, time - >>> unix_time = int(time.time()) # 当前UNIX Time,设其职为 1449313829 + >>> unix_time = int(time.time()) # 当前UNIX Time,设其值为 1449313829 >>> date_str = oss2.http_date(unix_time) # 得到 'Sat, 05 Dec 2015 11:10:29 GMT' >>> oss2.http_to_unixtime(date_str) # 得到 1449313829 @@ -948,8 +948,8 @@ def post_vod_playlist(self, channel_name, playlist_name, start_time = 0, end_tim param str channel_name: 要生成点播列表的live channel的名称 param str playlist_name: 要生成点播列表m3u8文件的名称 - param int start_time: 点播的起始时间,为UNIX时间戳 - param int end_time: 点播的结束时间,为UNIX时间戳 + param int start_time: 点播的起始时间,Unix Time格式,可以使用int(time.time())获取 + param int end_time: 点播的结束时间,Unix Time格式,可以使用int(time.time())获取 """ key = channel_name + "/" + playlist_name resp = self.__do_object('POST', key, params={Bucket.VOD: '', diff --git a/oss2/models.py b/oss2/models.py index 9f4e6bda..03ce0cd9 100644 --- a/oss2/models.py +++ b/oss2/models.py @@ -454,28 +454,41 @@ class LiveChannelInfo(object): """Live channel(直播频道)配置。 :param status: 直播频道的状态,合法的值为"enabled"和"disabled"。 - :type type: str + :type status: str :param description: 直播频道的描述信息,最长为128字节。 :type description: str - :param modified: 直播频道的最后修改时间,这个字段仅在ListLiveChannel时使用。 - :type modified: str - :param target: 直播频道的推流目标节点,包含目标协议相关的参数。 - :type class:`LiveChannelInfoTarget `""" - + :type class:`LiveChannelInfoTarget ` + + :param last_modified: 直播频道的最后修改时间,这个字段仅在`ListLiveChannel`时使用。 + :type last_modified: int, 参考 :ref:`unix_time`。 + + :param name: 直播频道的名称。 + :type name: str + + :param play_url: 播放地址。 + :type play_url: str + + :param publish_url: 推流地址。 + :type publish_url: str""" + def __init__(self, status = 'enabled', description = '', target = None, - modified = None, - name = None): + last_modified = None, + name = None, + play_url = None, + publish_url = None): self.status = status self.description = description self.target = target - self.modified = modified + self.last_modified = last_modified self.name = name + self.play_url = play_url + self.publish_url = publish_url class LiveChannelList(object): @@ -497,7 +510,7 @@ class LiveChannelList(object): :type marker: str :param channels: List返回的直播频道列表 - :type channels: list""" + :type channels: list,类型为 :class:`LiveChannelInfo`""" def __init__(self, prefix = '', @@ -575,7 +588,7 @@ class LiveChannelStat(object): :type remote_addr: str :param connected_time: 本次推流开始时间。 - :type connected_time: str + :type connected_time: int, unix time :param video: 视频描述信息。 :type video: class:`LiveChannelVideoStat ` @@ -600,10 +613,10 @@ class LiveRecord(object): """直播频道中的推流记录信息 :param start_time: 本次推流开始时间。 - :type start_time: str + :type start_time: int,参考 :ref:`unix_time`。 :param end_time: 本次推流结束时间。 - :type end_time: str + :type end_time: int, 参考 :ref:`unix_time`。 :param remote_addr: 推流时客户端的地址。 :type remote_addr: str""" diff --git a/oss2/xml_utils.py b/oss2/xml_utils.py index ef500a24..54b0f184 100644 --- a/oss2/xml_utils.py +++ b/oss2/xml_utils.py @@ -94,7 +94,6 @@ def _add_node_child(parent, tag): def parse_list_objects(result, body): root = ElementTree.fromstring(body) url_encoded = _is_url_encoding(root) - result.is_truncated = _find_bool(root, 'IsTruncated') if result.is_truncated: result.next_marker = _find_object(root, 'NextMarker', url_encoded) @@ -269,7 +268,9 @@ def parse_list_live_channel(result, body): result.marker = _find_tag(root, 'Marker') result.max_keys = _find_int(root, 'MaxKeys') result.is_truncated = _find_bool(root, 'IsTruncated') - result.next_marker = _find_tag(root, 'NextMarker') + + if result.is_truncated: + result.next_marker = _find_tag(root, 'NextMarker') channels = root.findall('LiveChannel') for channel in channels: @@ -277,7 +278,7 @@ def parse_list_live_channel(result, body): tmp.name = _find_tag(channel, 'Name') tmp.description = _find_tag(channel, 'Description') tmp.status = _find_tag(channel, 'Status') - tmp.modified = _find_tag(channel, 'LastModified') + tmp.last_modified = iso8601_to_unixtime(_find_tag(channel, 'LastModified')) tmp.play_url = _find_tag(channel, 'PlayUrls/Url') tmp.publish_url = _find_tag(channel, 'PublishUrls/Url') @@ -307,7 +308,7 @@ def parse_live_channel_stat(result, body): if root.find('RemoteAddr') is not None: result.remote_addr = _find_tag(root, 'RemoteAddr') if root.find('ConnectedTime') is not None: - result.connected_time = iso8601_to_date(_find_tag(root, 'ConnectedTime')) + result.connected_time = iso8601_to_unixtime(_find_tag(root, 'ConnectedTime')) video_node = root.find('Video') audio_node = root.find('Audio') @@ -328,8 +329,8 @@ def parse_live_channel_history(result, body): records = root.findall('LiveRecord') for record in records: tmp = LiveRecord() - tmp.start_time = _find_tag(record, 'StartTime') - tmp.end_time = _find_tag(record, 'EndTime') + tmp.start_time = iso8601_to_unixtime(_find_tag(record, 'StartTime')) + tmp.end_time = iso8601_to_unixtime(_find_tag(record, 'EndTime')) tmp.remote_addr = _find_tag(record, 'RemoteAddr') result.records.append(tmp) diff --git a/tests/test_mock_bucket.py b/tests/test_mock_bucket.py index 871881a9..6b909a41 100644 --- a/tests/test_mock_bucket.py +++ b/tests/test_mock_bucket.py @@ -742,9 +742,87 @@ def test_create_live_channel(self, do_request): self.assertRequest(req_info, request_text) + @patch('oss2.Session.do_request') + def test_list_live_channel(self, do_request): + from oss2.utils import iso8601_to_unixtime + + request_text = '''GET /?live= HTTP/1.1 +Host: ming-oss-share.oss-cn-hangzhou.aliyuncs.com +Accept-Encoding: identity +Connection: keep-alive +Accept: */* +User-Agent: aliyun-sdk-python/2.1.1(Windows/7/AMD64;2.7.10) +date: Tue, 09 Aug 2016 11:51:30 GMT +authorization: OSS 2NeLUvmJFYbrj2Eb:BQCNOYdGglcAbhdHhqTfVNtLBow=''' + + response_text = '''HTTP/1.1 200 OK +Server: AliyunOSS +Date: Tue, 09 Aug 2016 11:51:30 GMT +Content-Type: application/xml +Content-Length: 100 +Connection: keep-alive +x-oss-request-id: 57A9C3C27FBF67E9BE686908 +x-oss-server-time: 1 + + + + test + + 2 + true + test3 + + test1 + test1 + enabled + 2016-04-01T07:04:00.000Z + + rtmp://ming-oss-share.oss-cn-hangzhou.aliyuncs.com/live/test1 + + + http://ming-oss-share.oss-cn-hangzhou.aliyuncs.com/test1/playlist.m3u8 + + + + test2 + test2 + disabled + 2016-04-01T08:04:50.000Z + + rtmp://ming-oss-share.oss-cn-hangzhou.aliyuncs.com/live/test2 + + + http://ming-oss-share.oss-cn-hangzhou.aliyuncs.com/test2/playlist.m3u8 + + +''' + + req_info = unittests.common.mock_response(do_request, response_text) + result = unittests.common.bucket().list_live_channel('test', '', 2) + self.assertRequest(req_info, request_text) + + self.assertEqual(result.prefix, 'test') + self.assertEqual(result.marker, '') + self.assertEqual(result.max_keys, 2) + self.assertEqual(result.is_truncated, True) + self.assertEqual(result.next_marker, 'test3') + self.assertEqual(len(result.channels), 2) + self.assertEqual(result.channels[0].name, 'test1') + self.assertEqual(result.channels[0].description, 'test1') + self.assertEqual(result.channels[0].status, 'enabled') + self.assertEqual(result.channels[0].last_modified, iso8601_to_unixtime('2016-04-01T07:04:00.000Z')) + self.assertEqual(result.channels[0].publish_url, 'rtmp://ming-oss-share.oss-cn-hangzhou.aliyuncs.com/live/test1') + self.assertEqual(result.channels[0].play_url, 'http://ming-oss-share.oss-cn-hangzhou.aliyuncs.com/test1/playlist.m3u8') + self.assertEqual(result.channels[1].name, 'test2') + self.assertEqual(result.channels[1].description, 'test2') + self.assertEqual(result.channels[1].status, 'disabled') + self.assertEqual(result.channels[1].last_modified, iso8601_to_unixtime('2016-04-01T08:04:50.000Z')) + self.assertEqual(result.channels[1].publish_url, 'rtmp://ming-oss-share.oss-cn-hangzhou.aliyuncs.com/live/test2') + self.assertEqual(result.channels[1].play_url, 'http://ming-oss-share.oss-cn-hangzhou.aliyuncs.com/test2/playlist.m3u8') + @patch('oss2.Session.do_request') def test_get_live_channel_stat(self, do_request): - from oss2.utils import iso8601_to_date + from oss2.utils import iso8601_to_unixtime from oss2.models import LiveChannelAudioStat, LiveChannelVideoStat request_text = '''GET /lc?comp=stat&live= HTTP/1.1 @@ -791,7 +869,7 @@ def test_get_live_channel_stat(self, do_request): self.assertRequest(req_info, request_text) self.assertEqual(result.status, 'Live') - self.assertEqual(result.connected_time, iso8601_to_date('2016-08-08T05:59:28.000Z')) + self.assertEqual(result.connected_time, iso8601_to_unixtime('2016-08-08T05:59:28.000Z')) self.assertEqual(result.remote_addr, '8.8.8.8:57186') video = LiveChannelVideoStat(1280, 536, 24, 'H264', 214146) self.assertEqual(result.video.bandwidth, video.bandwidth) @@ -807,6 +885,7 @@ def test_get_live_channel_stat(self, do_request): @patch('oss2.Session.do_request') def test_get_live_channel_history(self, do_request): from oss2.models import LiveRecord + from oss2.utils import iso8601_to_unixtime request_text = '''GET /lc?comp=history&live= HTTP/1.1 Host: ming-oss-share.oss-cn-hangzhou.aliyuncs.com @@ -847,11 +926,15 @@ def test_get_live_channel_history(self, do_request): self.assertRequest(req_info, request_text) self.assertEqual(len(result.records), 2) - lr = LiveRecord('2016-08-06T05:59:28.000Z', '2016-08-06T06:02:43.000Z', '8.8.8.8:57186') + lr = LiveRecord(iso8601_to_unixtime('2016-08-06T05:59:28.000Z'), + iso8601_to_unixtime('2016-08-06T06:02:43.000Z'), + '8.8.8.8:57186') self.assertEqual(result.records[0].start_time, lr.start_time) self.assertEqual(result.records[0].end_time, lr.end_time) self.assertEqual(result.records[0].remote_addr, lr.remote_addr) - lr = LiveRecord('2016-08-06T06:16:20.000Z', '2016-08-06T06:16:25.000Z', '1.1.1.1:57365') + lr = LiveRecord(iso8601_to_unixtime('2016-08-06T06:16:20.000Z'), + iso8601_to_unixtime('2016-08-06T06:16:25.000Z'), + '1.1.1.1:57365') self.assertEqual(result.records[1].start_time, lr.start_time) self.assertEqual(result.records[1].end_time, lr.end_time) self.assertEqual(result.records[1].remote_addr, lr.remote_addr) From e36a1caee8ecf3e220c4ed58873c2d9253eeb3ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B8=A3=E9=95=9D?= Date: Fri, 12 Aug 2016 17:12:09 +0800 Subject: [PATCH 2/2] rtmp --- unittests/test_bucket.py | 182 --------------------------------------- 1 file changed, 182 deletions(-) diff --git a/unittests/test_bucket.py b/unittests/test_bucket.py index 42dadcd1..76809b9e 100644 --- a/unittests/test_bucket.py +++ b/unittests/test_bucket.py @@ -701,188 +701,6 @@ def test_get_location(self, do_request): self.assertRequest(req_info, request_text) self.assertEqual(result.location, 'oss-cn-hangzhou') - @patch('oss2.Session.do_request') - def test_create_live_channel(self, do_request): - request_text = '''PUT /lc?live= HTTP/1.1 -Host: ming-oss-share.oss-cn-hangzhou.aliyuncs.com -Accept-Encoding: identity -Connection: keep-alive -Accept: */* -User-Agent: aliyun-sdk-python/2.1.1(Windows/7/AMD64;2.7.10) -date: Tue, 09 Aug 2016 11:25:01 GMT -authorization: OSS 2NeLUvmJFYbrj2Eb:ljTfGW1yYoTGQN7Tl9gU36kJcxQ= -Content-Length: 217 - -enabledHLS53test.m3u8''' - - response_text = '''HTTP/1.1 200 OK -Server: AliyunOSS -Date: Tue, 09 Aug 2016 11:25:01 GMT -Content-Type: application/xml -Content-Length: 437 -Connection: keep-alive -x-oss-request-id: 57A9BD8D2FADF35D13CD7E5E -x-oss-server-time: 118 - - - - - rtmp://ming-oss-share.oss-cn-hangzhou.aliyuncs.com/live/lc - - - http://ming-oss-share.oss-cn-hangzhou.aliyuncs.com/lc/test.m3u8 - -''' - - req_info = mock_response(do_request, response_text) - - channel_target = oss2.models.LiveChannelInfoTarget(playlist_name="test.m3u8") - channel_info = oss2.models.LiveChannelInfo(target=channel_target) - bucket().create_live_channel("lc", channel_info) - - self.assertRequest(req_info, request_text) - - @patch('oss2.Session.do_request') - def test_get_live_channel_stat(self, do_request): - from oss2.utils import iso8601_to_date - from oss2.models import LiveChannelAudioStat, LiveChannelVideoStat - - request_text = '''GET /lc?comp=stat&live= HTTP/1.1 -Host: ming-oss-share.oss-cn-hangzhou.aliyuncs.com -Accept-Encoding: identity -Connection: keep-alive -Accept: */* -User-Agent: aliyun-sdk-python/2.1.1(Windows/7/AMD64;2.7.10) -date: Tue, 09 Aug 2016 11:51:30 GMT -authorization: OSS 2NeLUvmJFYbrj2Eb:BQCNOYdGglcAbhdHhqTfVNtLBow=''' - - response_text = '''HTTP/1.1 200 OK -Server: AliyunOSS -Date: Tue, 09 Aug 2016 11:51:30 GMT -Content-Type: application/xml -Content-Length: 100 -Connection: keep-alive -x-oss-request-id: 57A9C3C27FBF67E9BE686908 -x-oss-server-time: 1 - - - - Live - 2016-08-08T05:59:28.000Z - 8.8.8.8:57186 - - - -''' - - req_info = mock_response(do_request, response_text) - - result = bucket().get_live_channel_stat('lc') - - self.assertRequest(req_info, request_text) - self.assertEqual(result.status, 'Live') - self.assertEqual(result.connected_time, iso8601_to_date('2016-08-08T05:59:28.000Z')) - self.assertEqual(result.remote_addr, '8.8.8.8:57186') - video = LiveChannelVideoStat(1280, 536, 24, 'H264', 214146) - self.assertEqual(result.video.bandwidth, video.bandwidth) - self.assertEqual(result.video.codec, video.codec) - self.assertEqual(result.video.frame_rate, video.frame_rate) - self.assertEqual(result.video.height, video.height) - self.assertEqual(result.video.width, video.width) - audio = LiveChannelAudioStat('AAC', 22050, 11444) - self.assertEqual(result.audio.bandwidth, audio.bandwidth) - self.assertEqual(result.audio.codec, audio.codec) - self.assertEqual(result.audio.sample_rate, audio.sample_rate) - - @patch('oss2.Session.do_request') - def test_get_live_channel_history(self, do_request): - from oss2.models import LiveRecord - - request_text = '''GET /lc?comp=history&live= HTTP/1.1 -Host: ming-oss-share.oss-cn-hangzhou.aliyuncs.com -Accept-Encoding: identity -Connection: keep-alive -Accept: */* -User-Agent: aliyun-sdk-python/2.1.1(Windows/7/AMD64;2.7.10) -date: Tue, 09 Aug 2016 12:24:13 GMT -authorization: OSS 2NeLUvmJFYbrj2Eb:j9Fb7RinrXTyyX7FKtP5QAK0FZs=''' - - response_text = '''HTTP/1.1 200 OK -Server: AliyunOSS -Date: Tue, 09 Aug 2016 12:24:13 GMT -Content-Type: application/xml -Content-Length: 62 -Connection: keep-alive -x-oss-request-id: 57A9CB6DF3D45CE477C0227B -x-oss-server-time: 1 - - - - - 2016-08-06T05:59:28.000Z - 2016-08-06T06:02:43.000Z - 8.8.8.8:57186 - - - 2016-08-06T06:16:20.000Z - 2016-08-06T06:16:25.000Z - 1.1.1.1:57365 - - -''' - - req_info = mock_response(do_request, response_text) - - result = bucket().get_live_channel_history('lc') - - self.assertRequest(req_info, request_text) - self.assertEqual(len(result.records), 2) - lr = LiveRecord('2016-08-06T05:59:28.000Z', '2016-08-06T06:02:43.000Z', '8.8.8.8:57186') - self.assertEqual(result.records[0].start_time, lr.start_time) - self.assertEqual(result.records[0].end_time, lr.end_time) - self.assertEqual(result.records[0].remote_addr, lr.remote_addr) - lr = LiveRecord('2016-08-06T06:16:20.000Z', '2016-08-06T06:16:25.000Z', '1.1.1.1:57365') - self.assertEqual(result.records[1].start_time, lr.start_time) - self.assertEqual(result.records[1].end_time, lr.end_time) - self.assertEqual(result.records[1].remote_addr, lr.remote_addr) - - @patch('oss2.Session.do_request') - def test_post_vod_playlist(self, do_request): - request_text = '''POST /lc%2Ftest.m3u8?vod=&endTime=1470792140&startTime=1470788540 HTTP/1.1 -Host: ming-oss-share.oss-cn-hangzhou.aliyuncs.com -Accept-Encoding: identity -Connection: keep-alive -Accept: */* -User-Agent: aliyun-sdk-python/2.1.1(Windows/7/AMD64;2.7.10) -date: Wed, 10 Aug 2016 01:23:20 GMT -authorization: OSS 2NeLUvmJFYbrj2Eb:OifxZSHuzeR/Lp3hFJAqBw3VNy8= -Content-Length: 0''' - - response_text = '''HTTP/1.1 200 OK -Server: AliyunOSS -Date: Wed, 06 Apr 2016 06:00:21 GMT -Content-Length: 0 -Content-Type: application/xml -Connection: keep-alive -x-oss-request-id: 5704A5F5B9247571DF000031 -x-oss-server-time: 21 -''' - - req_info = mock_response(do_request, response_text) - - bucket().post_vod_playlist('lc', 'test.m3u8', 1470788540, 1470792140) - self.assertRequest(req_info, request_text) - if __name__ == '__main__': unittest.main() \ No newline at end of file