Skip to content

Commit 6ba27eb

Browse files
committed
fixing merge conflict
2 parents be522ab + c6f2588 commit 6ba27eb

File tree

7 files changed

+323
-51
lines changed

7 files changed

+323
-51
lines changed

README.rst

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,8 @@ The live streaming broadcast can target one HLS endpoint and up to five RTMP ser
438438
'stylesheet': 'the layout stylesheet (only used with type == custom)'
439439
},
440440
'maxDuration': 5400,
441+
'hasAudio': True
442+
'hasVideo': True
441443
'outputs': {
442444
'hls': {},
443445
'rtmp': [{
@@ -494,6 +496,37 @@ You can specify the following broadcast resolutions:
494496
To enable multiple simultaneous broadcasts on the same session, specify a unique value for the
495497
``multiBroadcastTag`` parameter in ``options`` when calling the ``opentok.start_broadcast`` method.
496498

499+
You can broadcast only audio, or only video, for a stream by setting ``hasAudio`` or ``hasVideo``
500+
to ``False`` as required. These fields are ``True`` by default.
501+
502+
.. code:: python
503+
504+
session_id = 'SESSIONID'
505+
options = {
506+
'layout': {
507+
'type': 'custom',
508+
'stylesheet': 'the layout stylesheet (only used with type == custom)'
509+
},
510+
'maxDuration': 5400,
511+
'hasAudio': True
512+
'hasVideo': False
513+
'outputs': {
514+
'hls': {},
515+
'rtmp': [{
516+
'id': 'foo',
517+
'serverUrl': 'rtmp://myfooserver/myfooapp',
518+
'streamName': 'myfoostream'
519+
}, {
520+
'id': 'bar',
521+
'serverUrl': 'rtmp://mybarserver/mybarapp',
522+
'streamName': 'mybarstream'
523+
}]
524+
},
525+
'resolution': '640x480'
526+
}
527+
528+
broadcast = opentok.start_broadcast(session_id, options)
529+
497530
You can stop a started Broadcast using the ``opentok.stop_broadcast(broadcast_id)`` method.
498531

499532
.. code:: python
@@ -657,6 +690,15 @@ to all clients connected to session or to a specific connection:
657690
# To a specific connection
658691
opentok.play_dtmf(session_id, connection_id, digits)
659692
693+
Appending to the User Agent
694+
-------
695+
696+
You can append a string to the user agent that is sent with requests:
697+
698+
.. code:: python
699+
700+
opentok.append_to_user_agent('my-appended-string')
701+
660702
Samples
661703
-------
662704

opentok/broadcast.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ class Broadcast(object):
2828
:ivar status:
2929
The status of the broadcast.
3030
31+
:ivar hasAudio:
32+
Whether the broadcast has audio.
33+
34+
:ivar hasVideo:
35+
Whether the broadcast has video.
36+
3137
:ivar broadcastUrls:
3238
An object containing details about the HLS and RTMP broadcasts.
3339
@@ -63,6 +69,8 @@ def __init__(self, kwargs):
6369
self.projectId = kwargs.get("projectId")
6470
self.createdAt = kwargs.get("createdAt")
6571
self.updatedAt = kwargs.get("updatedAt")
72+
self.hasAudio = kwargs.get("hasAudio")
73+
self.hasVideo = kwargs.get("hasVideo")
6674
self.resolution = kwargs.get("resolution")
6775
self.status = kwargs.get("status")
6876
self.broadcastUrls = kwargs.get("broadcastUrls")
@@ -71,7 +79,7 @@ def __init__(self, kwargs):
7179

7280
def json(self):
7381
"""
74-
Returns a JSON representation of the broadcast
82+
Returns a JSON representation of the broadcast.
7583
"""
7684
return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=4)
7785

opentok/opentok.py

Lines changed: 54 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,12 @@ class ArchiveModes(Enum):
9191

9292

9393
valid_archive_resolutions = {
94-
'640x480',
95-
'480x640',
96-
'1280x720',
97-
'720x1280',
98-
'1920x1080',
99-
'1080x1920',
94+
"640x480",
95+
"480x640",
96+
"1280x720",
97+
"720x1280",
98+
"1920x1080",
99+
"1080x1920",
100100
}
101101

102102
logger = logging.getLogger("opentok")
@@ -125,6 +125,9 @@ def __init__(
125125
self._proxies = None
126126
self.endpoints = Endpoints(api_url, self.api_key)
127127
self._app_version = __version__ if app_version == None else app_version
128+
self._user_agent = (
129+
f"OpenTok-Python-SDK/{self.app_version} python/{platform.python_version()}"
130+
)
128131
# JWT custom claims - Default values
129132
self._jwt_livetime = 3 # In minutes
130133

@@ -144,6 +147,13 @@ def app_version(self):
144147
def app_version(self, value):
145148
self._app_version = value
146149

150+
@property
151+
def user_agent(self):
152+
return self._user_agent
153+
154+
def append_to_user_agent(self, value):
155+
self._user_agent = self._user_agent + value
156+
147157
@property
148158
def jwt_livetime(self):
149159
return self._jwt_livetime
@@ -408,7 +418,7 @@ def create_session(
408418
"A session with always archive mode must also have the routed media mode."
409419
)
410420
)
411-
421+
412422
if archive_name is not None:
413423
if archive_mode == ArchiveModes.manual:
414424
raise OpenTokException(
@@ -418,7 +428,7 @@ def create_session(
418428
raise OpenTokException(
419429
"archive_name must be between 1 and 80 characters in length."
420430
)
421-
431+
422432
if archive_resolution is not None:
423433
if archive_mode == ArchiveModes.manual:
424434
raise OpenTokException(
@@ -631,13 +641,13 @@ def start_archive(
631641
}
632642

633643
if layout is not None:
634-
payload['layout'] = layout
644+
payload["layout"] = layout
635645

636646
logger.debug(
637647
"POST to %r with params %r, headers %r, proxies %r",
638648
self.endpoints.archive_url(),
639649
json.dumps(payload),
640-
self.json_headers(),
650+
self.get_json_headers(),
641651
self.proxies,
642652
)
643653

@@ -683,7 +693,7 @@ def stop_archive(self, archive_id):
683693
logger.debug(
684694
"POST to %r with headers %r, proxies %r",
685695
self.endpoints.archive_url(archive_id) + "/stop",
686-
self.json_headers(),
696+
self.get_json_headers(),
687697
self.proxies,
688698
)
689699

@@ -718,7 +728,7 @@ def delete_archive(self, archive_id):
718728
logger.debug(
719729
"DELETE to %r with headers %r, proxies %r",
720730
self.endpoints.archive_url(archive_id),
721-
self.json_headers(),
731+
self.get_json_headers(),
722732
self.proxies,
723733
)
724734

@@ -748,7 +758,7 @@ def get_archive(self, archive_id):
748758
logger.debug(
749759
"GET to %r with headers %r, proxies %r",
750760
self.endpoints.archive_url(archive_id),
751-
self.json_headers(),
761+
self.get_json_headers(),
752762
self.proxies,
753763
)
754764

@@ -794,7 +804,7 @@ def get_archives(self, offset=None, count=None, session_id=None):
794804
logger.debug(
795805
"GET to %r with headers %r, proxies %r",
796806
endpoint,
797-
self.json_headers(),
807+
self.get_json_headers(),
798808
self.proxies,
799809
)
800810

@@ -942,7 +952,7 @@ def send_signal(self, session_id, payload, connection_id=None):
942952
"POST to %r with params %r, headers %r, proxies %r",
943953
self.endpoints.signaling_url(session_id, connection_id),
944954
json.dumps(payload),
945-
self.json_headers(),
955+
self.get_json_headers(),
946956
self.proxies,
947957
)
948958

@@ -997,7 +1007,7 @@ def get_stream(self, session_id, stream_id):
9971007
logger.debug(
9981008
"GET to %r with headers %r, proxies %r",
9991009
endpoint,
1000-
self.json_headers(),
1010+
self.get_json_headers(),
10011011
self.proxies,
10021012
)
10031013

@@ -1034,7 +1044,7 @@ def list_streams(self, session_id):
10341044
logger.debug(
10351045
"GET to %r with headers %r, proxies %r",
10361046
endpoint,
1037-
self.json_headers(),
1047+
self.get_json_headers(),
10381048
self.proxies,
10391049
)
10401050

@@ -1072,7 +1082,7 @@ def force_disconnect(self, session_id, connection_id):
10721082
logger.debug(
10731083
"DELETE to %r with headers %r, proxies %r",
10741084
endpoint,
1075-
self.json_headers(),
1085+
self.get_json_headers(),
10761086
self.proxies,
10771087
)
10781088

@@ -1134,7 +1144,7 @@ def set_archive_layout(
11341144
"PUT to %r with params %r, headers %r, proxies %r",
11351145
endpoint,
11361146
json.dumps(payload),
1137-
self.json_headers(),
1147+
self.get_json_headers(),
11381148
self.proxies,
11391149
)
11401150

@@ -1263,7 +1273,7 @@ def dial(self, session_id, token, sip_uri, options=[]):
12631273
"POST to %r with params %r, headers %r, proxies %r",
12641274
endpoint,
12651275
json.dumps(payload),
1266-
self.json_headers(),
1276+
self.get_json_headers(),
12671277
self.proxies,
12681278
)
12691279

@@ -1317,7 +1327,7 @@ class names (Strings) to apply to the stream. For example:
13171327
"PUT to %r with params %r, headers %r, proxies %r",
13181328
endpoint,
13191329
json.dumps(items_payload),
1320-
self.json_headers(),
1330+
self.get_json_headers(),
13211331
self.proxies,
13221332
)
13231333

@@ -1354,6 +1364,10 @@ def start_broadcast(
13541364
13551365
:param String session_id: The session ID of the OpenTok session you want to broadcast
13561366
1367+
:param Boolean optional hasAudio: Whether the stream is broadcast with audio.
1368+
1369+
:param Boolean optional hasVideo: Whether the stream is broadcast with video.
1370+
13571371
:param Dictionary options, with the following properties:
13581372
13591373
Dictionary 'layout' optional: Specify this to assign the initial layout type for the
@@ -1414,18 +1428,18 @@ def start_broadcast(
14141428
BroadcastStreamModes.manual to explicitly select streams to include in the the broadcast, using the
14151429
OpenTok.add_broadcast_stream() and OpenTok.remove_broadcast_stream() methods.
14161430
1417-
:rtype A Broadcast object, which contains information of the broadcast: id, sessionId
1431+
:rtype A Broadcast object, which contains information of the broadcast: id, sessionId,
14181432
projectId, createdAt, updatedAt, resolution, status and broadcastUrls
14191433
"""
14201434

1421-
if 'hls' in options['outputs']:
1435+
if "hls" in options["outputs"]:
14221436
if (
1423-
'lowLatency' in options['outputs']['hls']
1424-
and 'dvr' in options['outputs']['hls']
1437+
"lowLatency" in options["outputs"]["hls"]
1438+
and "dvr" in options["outputs"]["hls"]
14251439
):
14261440
if (
1427-
options['outputs']['hls']['lowLatency'] == True
1428-
and options['outputs']['hls']['dvr'] == True
1441+
options["outputs"]["hls"]["lowLatency"] == True
1442+
and options["outputs"]["hls"]["dvr"] == True
14291443
):
14301444
raise BroadcastHLSOptionsError(
14311445
'HLS options "lowLatency" and "dvr" cannot both be set to "True".'
@@ -1441,7 +1455,7 @@ def start_broadcast(
14411455
"POST to %r with params %r, headers %r, proxies %r",
14421456
endpoint,
14431457
json.dumps(payload),
1444-
self.json_headers(),
1458+
self.get_json_headers(),
14451459
self.proxies,
14461460
)
14471461

@@ -1484,7 +1498,7 @@ def stop_broadcast(self, broadcast_id):
14841498
logger.debug(
14851499
"POST to %r with headers %r, proxies %r",
14861500
endpoint,
1487-
self.json_headers(),
1501+
self.get_json_headers(),
14881502
self.proxies,
14891503
)
14901504

@@ -1621,7 +1635,7 @@ def get_broadcast(self, broadcast_id):
16211635
logger.debug(
16221636
"GET to %r with headers %r, proxies %r",
16231637
endpoint,
1624-
self.json_headers(),
1638+
self.get_json_headers(),
16251639
self.proxies,
16261640
)
16271641

@@ -1680,7 +1694,7 @@ def set_broadcast_layout(
16801694
"PUT to %r with params %r, headers %r, proxies %r",
16811695
endpoint,
16821696
json.dumps(payload),
1683-
self.json_headers(),
1697+
self.get_json_headers(),
16841698
self.proxies,
16851699
)
16861700

@@ -1929,10 +1943,10 @@ def connect_audio_to_websocket(
19291943
def validate_websocket_options(self, options):
19301944
if type(options) is not dict:
19311945
raise InvalidWebSocketOptionsError(
1932-
'Must pass WebSocket options as a dictionary.'
1946+
"Must pass WebSocket options as a dictionary."
19331947
)
1934-
if 'uri' not in options:
1935-
raise InvalidWebSocketOptionsError('Provide a WebSocket URI.')
1948+
if "uri" not in options:
1949+
raise InvalidWebSocketOptionsError("Provide a WebSocket URI.")
19361950

19371951
def _sign_string(self, string, secret):
19381952
return hmac.new(
@@ -1974,9 +1988,9 @@ def mute_all(
19741988

19751989
try:
19761990
if excludedStreamIds:
1977-
options = {'active': True, 'excludedStreams': excludedStreamIds}
1991+
options = {"active": True, "excludedStreams": excludedStreamIds}
19781992
else:
1979-
options = {'active': True, 'excludedStreams': []}
1993+
options = {"active": True, "excludedStreams": []}
19801994

19811995
response = requests.post(
19821996
url, headers=self.get_headers(), data=json.dumps(options)
@@ -2012,7 +2026,7 @@ def disable_force_mute(self, session_id: str) -> requests.Response:
20122026
:param session_id The session ID.
20132027
"""
20142028

2015-
options = {'active': False}
2029+
options = {"active": False}
20162030
url = self.endpoints.get_mute_all_url(session_id)
20172031

20182032
response = requests.post(
@@ -2162,9 +2176,9 @@ def mute_all(
21622176

21632177
try:
21642178
if excludedStreamIds:
2165-
options = {'active': True, 'excludedStreams': excludedStreamIds}
2179+
options = {"active": True, "excludedStreams": excludedStreamIds}
21662180
else:
2167-
options = {'active': True, 'excludedStreams': []}
2181+
options = {"active": True, "excludedStreams": []}
21682182

21692183
response = requests.post(
21702184
url, headers=self.get_headers(), data=json.dumps(options)
@@ -2198,7 +2212,7 @@ def disable_force_mute(self, session_id: str) -> requests.Response:
21982212
:param session_id The session ID.
21992213
"""
22002214

2201-
options = {'active': False}
2215+
options = {"active": False}
22022216
url = self.endpoints.get_mute_all_url(session_id)
22032217

22042218
response = requests.post(

0 commit comments

Comments
 (0)