|
25 | 25 | from .stream import Stream
|
26 | 26 | from .streamlist import StreamList
|
27 | 27 | from .sip_call import SipCall
|
| 28 | +from .broadcast import Broadcast |
28 | 29 | from .exceptions import (
|
29 | 30 | OpenTokException,
|
30 | 31 | RequestError,
|
|
35 | 36 | GetStreamError,
|
36 | 37 | ForceDisconnectError,
|
37 | 38 | SipDialError,
|
38 |
| - SetStreamClassError |
| 39 | + SetStreamClassError, |
| 40 | + BroadcastError |
39 | 41 | )
|
40 | 42 |
|
41 | 43 | class Roles(Enum):
|
@@ -761,6 +763,176 @@ class names (Strings) to apply to the stream. For example:
|
761 | 763 | else:
|
762 | 764 | raise RequestError('OpenTok server error.', response.status_code)
|
763 | 765 |
|
| 766 | + def start_broadcast(self, session_id, options): |
| 767 | + """ |
| 768 | + Use this method to start a live streaming for an OpenTok session. This broadcasts the |
| 769 | + session to an HLS (HTTP live streaming) or to RTMP streams. To successfully start |
| 770 | + broadcasting a session, at least one client must be connected to the session. You can only |
| 771 | + start live streaming for sessions that use the OpenTok Media Router (with the media mode set |
| 772 | + to routed); you cannot use live streaming with sessions that have the media mode set to |
| 773 | + relayed |
| 774 | +
|
| 775 | + :param String session_id: The session ID of the OpenTok session you want to broadcast |
| 776 | +
|
| 777 | + :param Dictionary options, with the following properties: |
| 778 | +
|
| 779 | + Dictionary 'layout' optional: Specify this to assign the initial layout type for the |
| 780 | + broadcast. Valid values for the layout property are "bestFit", "custom", |
| 781 | + "horizontalPresentation", "pip" and "verticalPresentation". If you specify a "custom" |
| 782 | + layout type, set the stylesheet property of the layout object to the stylesheet. |
| 783 | + If you do not specify an initial layout type, the broadcast stream uses the Best Fit |
| 784 | + layout type |
| 785 | +
|
| 786 | + Integer 'maxDuration' optional: The maximum duration for the broadcast, in seconds. |
| 787 | + The broadcast will automatically stop when the maximum duration is reached. You can |
| 788 | + set the maximum duration to a value from 60 (60 seconds) to 36000 (10 hours). The |
| 789 | + default maximum duration is 2 hours (7200 seconds) |
| 790 | +
|
| 791 | + Dictionary 'outputs': This object defines the types of broadcast streams you want to |
| 792 | + start (both HLS and RTMP). You can include HLS, RTMP, or both as broadcast streams. |
| 793 | + If you include RTMP streaming, you can specify up to five target RTMP streams. For |
| 794 | + each RTMP stream, specify 'serverUrl' (the RTMP server URL), 'streamName' (the stream |
| 795 | + name, such as the YouTube Live stream name or the Facebook stream key), and |
| 796 | + (optionally) 'id' (a unique ID for the stream) |
| 797 | +
|
| 798 | + String 'resolution' optional: The resolution of the broadcast, either "640x480" |
| 799 | + (SD, the default) or "1280x720" (HD) |
| 800 | +
|
| 801 | + :rtype A Broadcast object, which contains information of the broadcast: id, sessionId |
| 802 | + projectId, createdAt, updatedAt, resolution, status and broadcastUrls |
| 803 | + """ |
| 804 | + payload = { |
| 805 | + 'sessionId': session_id |
| 806 | + } |
| 807 | + |
| 808 | + payload.update(options) |
| 809 | + |
| 810 | + endpoint = self.endpoints.broadcast_url() |
| 811 | + response = requests.post( |
| 812 | + endpoint, |
| 813 | + data=json.dumps(payload), |
| 814 | + headers=self.json_headers(), |
| 815 | + proxies=self.proxies, |
| 816 | + timeout=self.timeout |
| 817 | + ) |
| 818 | + |
| 819 | + if response.status_code == 200: |
| 820 | + return Broadcast(response.json()) |
| 821 | + elif response.status_code == 400: |
| 822 | + raise BroadcastError( |
| 823 | + 'Invalid request. This response may indicate that data in your request data is ' |
| 824 | + 'invalid JSON. It may also indicate that you passed in invalid layout options. ' |
| 825 | + 'Or you have exceeded the limit of five simultaneous RTMP streams for an OpenTok ' |
| 826 | + 'session. Or you specified and invalid resolution.') |
| 827 | + elif response.status_code == 403: |
| 828 | + raise AuthError('Authentication error.') |
| 829 | + elif response.status_code == 409: |
| 830 | + raise BroadcastError('The broadcast has already started for the session.') |
| 831 | + else: |
| 832 | + raise RequestError('OpenTok server error.', response.status_code) |
| 833 | + |
| 834 | + def stop_broadcast(self, broadcast_id): |
| 835 | + """ |
| 836 | + Use this method to stop a live broadcast of an OpenTok session |
| 837 | +
|
| 838 | + :param String broadcast_id: The ID of the broadcast you want to stop |
| 839 | +
|
| 840 | + :rtype A Broadcast object, which contains information of the broadcast: id, sessionId |
| 841 | + projectId, createdAt, updatedAt and resolution |
| 842 | + """ |
| 843 | + endpoint = self.endpoints.broadcast_url(broadcast_id, stop=True) |
| 844 | + response = requests.post( |
| 845 | + endpoint, |
| 846 | + headers=self.json_headers(), |
| 847 | + proxies=self.proxies, |
| 848 | + timeout=self.timeout |
| 849 | + ) |
| 850 | + |
| 851 | + if response.status_code == 200: |
| 852 | + return Broadcast(response.json()) |
| 853 | + elif response.status_code == 400: |
| 854 | + raise BroadcastError( |
| 855 | + 'Invalid request. This response may indicate that data in your request ' |
| 856 | + 'data is invalid JSON.') |
| 857 | + elif response.status_code == 403: |
| 858 | + raise AuthError('Authentication error.') |
| 859 | + elif response.status_code == 409: |
| 860 | + raise BroadcastError( |
| 861 | + 'The broadcast (with the specified ID) was not found or it has already ' |
| 862 | + 'stopped.') |
| 863 | + else: |
| 864 | + raise RequestError('OpenTok server error.', response.status_code) |
| 865 | + |
| 866 | + def get_broadcast(self, broadcast_id): |
| 867 | + """ |
| 868 | + Use this method to get details on a broadcast that is in-progress. |
| 869 | +
|
| 870 | + :param String broadcast_id: The ID of the broadcast you want to stop |
| 871 | +
|
| 872 | + :rtype A Broadcast object, which contains information of the broadcast: id, sessionId |
| 873 | + projectId, createdAt, updatedAt, resolution, broadcastUrls and status |
| 874 | + """ |
| 875 | + endpoint = self.endpoints.broadcast_url(broadcast_id) |
| 876 | + response = requests.get( |
| 877 | + endpoint, |
| 878 | + headers=self.json_headers(), |
| 879 | + proxies=self.proxies, |
| 880 | + timeout=self.timeout |
| 881 | + ) |
| 882 | + |
| 883 | + if response.status_code == 200: |
| 884 | + return Broadcast(response.json()) |
| 885 | + elif response.status_code == 400: |
| 886 | + raise BroadcastError( |
| 887 | + 'Invalid request. This response may indicate that data in your request ' |
| 888 | + 'data is invalid JSON.') |
| 889 | + elif response.status_code == 403: |
| 890 | + raise AuthError('Authentication error.') |
| 891 | + elif response.status_code == 409: |
| 892 | + raise BroadcastError('No matching broadcast found (with the specified ID).') |
| 893 | + else: |
| 894 | + raise RequestError('OpenTok server error.', response.status_code) |
| 895 | + |
| 896 | + def set_broadcast_layout(self, broadcast_id, layout_type, stylesheet=None): |
| 897 | + """ |
| 898 | + Use this method to change the layout type of a live streaming broadcast |
| 899 | +
|
| 900 | + :param String broadcast_id: The ID of the broadcast that will be updated |
| 901 | +
|
| 902 | + :param String layout_type: The layout type for the broadcast. Valid values are: |
| 903 | + 'bestFit', 'custom', 'horizontalPresentation', 'pip' and 'verticalPresentation' |
| 904 | +
|
| 905 | + :param String stylesheet optional: CSS used to style the custom layout. |
| 906 | + Specify this only if you set the type property to 'custom' |
| 907 | + """ |
| 908 | + payload = { |
| 909 | + 'type': layout_type, |
| 910 | + } |
| 911 | + |
| 912 | + if layout_type == 'custom': |
| 913 | + if stylesheet is not None: |
| 914 | + payload['stylesheet'] = stylesheet |
| 915 | + |
| 916 | + endpoint = self.endpoints.broadcast_url(broadcast_id, layout=True) |
| 917 | + response = requests.put( |
| 918 | + endpoint, |
| 919 | + data=json.dumps(payload), |
| 920 | + headers=self.json_headers(), |
| 921 | + proxies=self.proxies, |
| 922 | + timeout=self.timeout |
| 923 | + ) |
| 924 | + |
| 925 | + if response.status_code == 200: |
| 926 | + pass |
| 927 | + elif response.status_code == 400: |
| 928 | + raise BroadcastError( |
| 929 | + 'Invalid request. This response may indicate that data in your request data is ' |
| 930 | + 'invalid JSON. It may also indicate that you passed in invalid layout options.') |
| 931 | + elif response.status_code == 403: |
| 932 | + raise AuthError('Authentication error.') |
| 933 | + else: |
| 934 | + raise RequestError('OpenTok server error.', response.status_code) |
| 935 | + |
764 | 936 | def _sign_string(self, string, secret):
|
765 | 937 | return hmac.new(secret.encode('utf-8'), string.encode('utf-8'), hashlib.sha1).hexdigest()
|
766 | 938 |
|
|
0 commit comments