Skip to content

Commit a8a1674

Browse files
Feature/manual stream mode minimal (#291)
* Minimal changes to implement and test streammode * Add the new response for manual mode * Added streamMode enum object for better validation * Take out offending lines in tests that will not pass on CI but aren't related to what we're testing * New methods for being able to add and remove streams from manual mode broadcasts and archives * Fix missing terminator * Added tests for stream mode, php8.1 compatibility, fixed client call to encode payload * Reference docs edits for selective stream archive/broadcast enhancements * Readme edits Co-authored-by: Jeff Swartz <[email protected]>
1 parent a35aab8 commit a8a1674

File tree

16 files changed

+823
-27
lines changed

16 files changed

+823
-27
lines changed

README.md

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,18 @@
44

55
<img src="https://assets.tokbox.com/img/vonage/Vonage_VideoAPI_black.svg" height="48px" alt="Tokbox is now known as Vonage" />
66

7-
The OpenTok PHP SDK lets you generate [sessions](http://tokbox.com/developer/guides/create-session/) and
8-
[tokens](http://tokbox.com/developer/guides/create-token/) for [OpenTok](http://www.tokbox.com/)
9-
applications, and [archive](http://tokbox.com/developer/guides/archiving/) sessions.
10-
It also includes methods for working with OpenTok
11-
[archives](http://tokbox.com/developer/guides/archiving), working with OpenTok
12-
[SIP interconnect](http://tokbox.com/developer/guides/sip), and
13-
[disconnecting clients from sessions](http://tokbox.com/developer/guides/moderation/rest/).
7+
The OpenTok PHP SDK provides methods for:
8+
9+
* Generating
10+
[sessions](https://tokbox.com/developer/guides/create-session/) and
11+
[tokens](https://tokbox.com/developer/guides/create-token/) for
12+
[OpenTok](https://www.tokbox.com/) applications that run on the .NET platform
13+
* Working with [OpenTok archives](https://tokbox.com/opentok/tutorials/archiving)
14+
* Working with [OpenTok live streaming broadcasts](https://tokbox.com/developer/guides/broadcast/live-streaming/)
15+
* Working with [OpenTok SIP interconnect](https://tokbox.com/developer/guides/sip)
16+
* [Sending signals to clients connected to a session](https://www.tokbox.com/developer/guides/signaling/)
17+
* [Disconnecting clients from sessions](https://tokbox.com/developer/guides/moderation/rest/)
18+
* [Forcing clients in a session to disconnect or mute published audio](https://tokbox.com/developer/guides/moderation/)
1419

1520
## Installation
1621

@@ -370,6 +375,17 @@ use OpenTok\OpenTok;
370375
$opentok->forceDisconnect($sessionId, $connectionId);
371376
```
372377

378+
### Forcing clients in a session mute published audio
379+
380+
You can force the publisher of a specific stream to stop publishing audio using the
381+
`Opentok.forceMuteStream($sessionId, $stream)` method.
382+
383+
You can force the publisher of all streams in a session (except for an optional list of streams)
384+
to stop publishing audio using the `Opentok.forceMuteAll($sessionId, $excludedStreamIds)` method.
385+
You can then disable the mute state of the session by calling the
386+
`Opentok.DisableForceMute(sessionId)` or `Opentok.DisableForceMuteAsync(sessionId)`
387+
method.
388+
373389
### Sending Signals
374390

375391
Once a Session is created, you can send signals to everyone in the session or to a specific connection.

src/OpenTok/Archive.php

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,17 @@
4949
* @property string $size
5050
* The size of the MP4 file. For archives that have not been generated, this value is set to 0.
5151
*
52+
* @property string $streamMode
53+
* Whether streams included in the archive are selected automatically (<code>StreamMode.AUTO</code>) or
54+
* manually (<code>StreamMode.MANUAL</code>). When streams are selected automatically (<code>StreamMode.AUTO</code>),
55+
* all streams in the session can be included in the archive. When streams are selected manually
56+
* (<code>StreamMode.MANUAL</code>), you specify streams to be included based on calls to the
57+
* <code>Archive.addStreamToArchive()</code> and <code>Archive.removeStreamFromArchive()</code> methods.
58+
* With manual mode, you can specify whether a stream's audio, video, or both are included in the
59+
* archive. In both automatic and manual modes, the archive composer includes streams based on
60+
* <a href="https://tokbox.com/developer/guides/archive-broadcast-layout/#stream-prioritization-rules">stream
61+
* prioritization rules</a>.
62+
*
5263
* @property string $status
5364
* The status of the archive, which can be one of the following:
5465
*
@@ -95,14 +106,16 @@ public function __construct($archiveData, $options = array())
95106
'apiKey' => null,
96107
'apiSecret' => null,
97108
'apiUrl' => 'https://api.opentok.com',
98-
'client' => null
109+
'client' => null,
110+
'streamMode' => StreamMode::AUTO
99111
);
100112
$options = array_merge($defaults, array_intersect_key($options, $defaults));
101-
list($apiKey, $apiSecret, $apiUrl, $client) = array_values($options);
113+
list($apiKey, $apiSecret, $apiUrl, $client, $streamMode) = array_values($options);
102114

103115
// validate params
104116
Validators::validateArchiveData($archiveData);
105117
Validators::validateClient($client);
118+
Validators::validateHasStreamMode($streamMode);
106119

107120
$this->data = $archiveData;
108121

@@ -137,6 +150,7 @@ public function __get($name)
137150
case 'hasAudio':
138151
case 'outputMode':
139152
case 'resolution':
153+
case 'streamMode':
140154
return $this->data[$name];
141155
default:
142156
return null;
@@ -202,6 +216,65 @@ public function toJson()
202216
return json_encode($this->jsonSerialize());
203217
}
204218

219+
/**
220+
* Adds a stream to a currently running archive that was started with the
221+
* the <code>streamMode</code> set to <code>StreamMode.Manual</code>. You can call the method
222+
* repeatedly with the same stream ID, to toggle the stream's audio or video in the archive.
223+
*
224+
* @param String $streamId The stream ID.
225+
* @param Boolean $hasAudio Whether the archive should include the stream's audio (true, the default)
226+
* or not (false).
227+
* @param Boolean $hasVideo Whether the archive should include the stream's video (true, the default)
228+
* or not (false).
229+
*
230+
* @return Boolean Returns true on success.
231+
*/
232+
public function addStreamToArchive(string $streamId, bool $hasAudio, bool $hasVideo): bool
233+
{
234+
if ($this->streamMode === StreamMode::AUTO) {
235+
throw new InvalidArgumentException('Cannot add stream to an Archive in auto stream mode');
236+
}
237+
238+
if ($hasAudio === false && $hasVideo === false) {
239+
throw new InvalidArgumentException('Both hasAudio and hasVideo cannot be false');
240+
}
241+
242+
if ($this->client->addStreamToArchive(
243+
$this->data['id'],
244+
$streamId,
245+
$hasVideo,
246+
$hasVideo
247+
)) {
248+
return true;
249+
}
250+
251+
return false;
252+
}
253+
254+
/**
255+
* Removes a stream from a currently running archive that was started with the
256+
* the <code>streamMode</code> set to <code>StreamMode.Manual</code>.
257+
*
258+
* @param String $streamId The stream ID.
259+
*
260+
* @return Boolean Returns true on success.
261+
*/
262+
public function removeStreamFromArchive(string $streamId): bool
263+
{
264+
if ($this->streamMode === StreamMode::AUTO) {
265+
throw new InvalidArgumentException('Cannot remove stream to an Archive in auto stream mode');
266+
}
267+
268+
if ($this->client->removeStreamFromArchive(
269+
$this->data['id'],
270+
$streamId
271+
)) {
272+
return true;
273+
}
274+
275+
return false;
276+
}
277+
205278
/**
206279
* Returns an associative array representation of this Archive object.
207280
* @deprecated 3.0.0 A more standard name for this method is supplied by JsonSerializable

src/OpenTok/ArchiveMode.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ abstract class ArchiveMode extends BasicEnum
1717
* The session is not archived automatically. To archive the session, you can call the
1818
* \OpenTok\OpenTok->startArchive() method.
1919
*/
20-
const MANUAL = 'manual';
20+
public const MANUAL = 'manual';
2121
/**
2222
* The session is archived automatically (as soon as there are clients connected
2323
* to the session).
2424
*/
25-
const ALWAYS = 'always';
25+
public const ALWAYS = 'always';
2626
}

src/OpenTok/Broadcast.php

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,17 @@
3434
*
3535
* @property boolean $isStopped
3636
* Whether the broadcast is stopped (true) or in progress (false).
37+
*
38+
* @property string $streamMode
39+
* Whether streams included in the broadcast are selected automatically (<code>StreamMode.AUTO</code>)
40+
* or manually (<code>StreamMode.MANUAL</code>). When streams are selected automatically (<code>StreamMode.AUTO</code>),
41+
* all streams in the session can be included in the broadcast. When streams are selected manually
42+
* (<code>StreamMode.MANUAL</code>), you specify streams to be included based on calls to the
43+
* <code>Broadcast.addStreamToBroadcast()</code> and <code>Broadcast.removeStreamFromBroadcast()</code> methods.
44+
* With manual mode, you can specify whether a stream's audio, video, or both are included in the
45+
* broadcast. In both automatic and manual modes, the broadcast composer includes streams based on
46+
* <a href="https://tokbox.com/developer/guides/archive-broadcast-layout/#stream-prioritization-rules">stream
47+
* prioritization rules</a>.
3748
*/
3849
class Broadcast
3950
{
@@ -55,14 +66,16 @@ public function __construct($broadcastData, $options = array())
5566
'apiSecret' => null,
5667
'apiUrl' => 'https://api.opentok.com',
5768
'client' => null,
58-
'isStopped' => false
69+
'isStopped' => false,
70+
'streamMode' => StreamMode::AUTO
5971
);
6072
$options = array_merge($defaults, array_intersect_key($options, $defaults));
61-
list($apiKey, $apiSecret, $apiUrl, $client, $isStopped) = array_values($options);
73+
list($apiKey, $apiSecret, $apiUrl, $client, $isStopped, $streamMode) = array_values($options);
6274

6375
// validate params
6476
Validators::validateBroadcastData($broadcastData);
6577
Validators::validateClient($client);
78+
Validators::validateHasStreamMode($streamMode);
6679

6780
$this->data = $broadcastData;
6881

@@ -91,6 +104,7 @@ public function __get($name)
91104
case 'status':
92105
case 'maxDuration':
93106
case 'resolution':
107+
case 'streamMode':
94108
return $this->data[$name];
95109
case 'hlsUrl':
96110
return $this->data['broadcastUrls']['hls'];
@@ -149,6 +163,65 @@ public function updateLayout($layout)
149163
$this->client->updateLayout($this->id, $layout, 'broadcast');
150164
}
151165

166+
/**
167+
* Adds a stream to a currently running broadcast that was started with the
168+
* the <code>streamMode</code> set to <code>StreamMode.Manual</code>. You can call the method
169+
* repeatedly with the same stream ID, to toggle the stream's audio or video in the broadcast.
170+
*
171+
* @param String $streamId The stream ID.
172+
* @param Boolean $hasAudio Whether the broadcast should include the stream's audio (true, the default)
173+
* or not (false).
174+
* @param Boolean $hasVideo Whether the broadcast should include the stream's video (true, the default)
175+
* or not (false).
176+
*
177+
* @return Boolean Returns true on success.
178+
*/
179+
public function addStreamToBroadcast(string $streamId, bool $hasAudio, bool $hasVideo): bool
180+
{
181+
if ($this->streamMode === StreamMode::AUTO) {
182+
throw new InvalidArgumentException('Cannot add stream to a Broadcast in auto stream mode');
183+
}
184+
185+
if ($hasAudio === false && $hasVideo === false) {
186+
throw new InvalidArgumentException('Both hasAudio and hasVideo cannot be false');
187+
}
188+
189+
if ($this->client->addStreamToBroadcast(
190+
$this->data['id'],
191+
$streamId,
192+
$hasVideo,
193+
$hasVideo
194+
)) {
195+
return true;
196+
}
197+
198+
return false;
199+
}
200+
201+
/**
202+
* Removes a stream from a currently running broadcast that was started with the
203+
* the <code>streamMode</code> set to <code>StreamMode.Manual</code>.
204+
*
205+
* @param String $streamId The stream ID.
206+
*
207+
* @return Boolean Returns true on success.
208+
*/
209+
public function removeStreamFromBroadcast(string $streamId): bool
210+
{
211+
if ($this->streamMode === StreamMode::AUTO) {
212+
throw new InvalidArgumentException('Cannot remove stream from a Broadcast in auto stream mode');
213+
}
214+
215+
if ($this->client->removeStreamFromBroadcast(
216+
$this->data['id'],
217+
$streamId
218+
)) {
219+
return true;
220+
}
221+
222+
return false;
223+
}
224+
152225
public function jsonSerialize()
153226
{
154227
return $this->data;

src/OpenTok/Layout.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ public function setScreenshareType(string $screenshareType): Layout
140140
throw new \RuntimeException('Screenshare type cannot be set on a layout type other than bestFit');
141141
}
142142

143+
#[\ReturnTypeWillChange]
143144
public function jsonSerialize()
144145
{
145146
return $this->toArray();

src/OpenTok/OpenTok.php

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,18 @@ public function createSession($options = array())
283283
* <code>hasVideo</code> to false, the call to the <code>startArchive()</code> method results
284284
* in an error.</li>
285285
*
286+
* <li><code>'streamMode'</code> (String) &mdash; Whether streams included in the archive are
287+
* selected automatically (<code>StreamMode.AUTO</code>, the default) or manually
288+
* (<code>StreamMode.MANUAL</code>). When streams are selected automatically
289+
* (<code>StreamMode.AUTO</code>), all streams in the session can be included in the archive.
290+
* When streams are selected manually (<code>StreamMode.MANUAL</code>), you specify streams
291+
* to be included based on calls to the <code>Archive.addStreamToArchive()</code> and
292+
* <code>Archive.removeStreamFromArchive()</code>. methods. With manual mode, you can specify
293+
* whether a stream's audio, video, or both are included in the archive. In both automatic and
294+
* manual modes, the archive composer includes streams based on
295+
* <a href="https://tokbox.com/developer/guides/archive-broadcast-layout/#stream-prioritization-rules">stream
296+
* prioritization rules</a>.</li>
297+
*
286298
* <li><code>'hasAudio'</code> (Boolean) &mdash; Whether the archive will record audio
287299
* (true, the default) or not (false). If you set both <code>hasAudio</code> and
288300
* <code>hasVideo</code> to false, the call to the <code>startArchive()</code> method results
@@ -315,15 +327,17 @@ public function startArchive(string $sessionId, $options = []): Archive
315327
'hasAudio' => true,
316328
'outputMode' => OutputMode::COMPOSED,
317329
'resolution' => null,
330+
'streamMode' => StreamMode::AUTO
318331
);
319332
$options = array_merge($defaults, array_intersect_key($options, $defaults));
320-
list($name, $hasVideo, $hasAudio, $outputMode, $resolution) = array_values($options);
333+
list($name, $hasVideo, $hasAudio, $outputMode, $resolution, $streamMode) = array_values($options);
321334
// validate arguments
322335
Validators::validateSessionId($sessionId);
323336
Validators::validateArchiveName($name);
324337
Validators::validateArchiveHasVideo($hasVideo);
325338
Validators::validateArchiveHasAudio($hasAudio);
326339
Validators::validateArchiveOutputMode($outputMode);
340+
Validators::validateHasStreamMode($streamMode);
327341

328342
if ((is_null($resolution) || empty($resolution)) && $outputMode === OutputMode::COMPOSED) {
329343
$options['resolution'] = "640x480";
@@ -598,6 +612,19 @@ public function disableForceMute(string $sessionId, array $options): bool
598612
* <a href="https://tokbox.com/developer/guides/broadcast/live-streaming/#configuring-live-streaming-video-layout">Configuring
599613
* Video Layout for the OpenTok live streaming feature</a>.
600614
* </li>
615+
*
616+
* <li><code>'streamMode'</code> (String) &mdash; Whether streams included in the broadcast
617+
* are selected automatically (<code>StreamMode.AUTO</code>, the default) or manually
618+
* (<code>StreamMode.MANUAL</code>). When streams are selected automatically
619+
* (<code>StreamMode.AUTO</code>), all streams in the session can be included in the broadcast.
620+
* When streams are selected manually (<code>StreamMode.MANUAL</code>), you specify streams
621+
* to be included based on calls to the <code>Broadcast.addStreamToBroadcast()</code> and
622+
* <code>Broadcast.removeStreamFromBroadcast()</code> methods. With manual mode, you can specify
623+
* whether a stream's audio, video, or both are included in the broadcast. In both automatic and
624+
* manual modes, the broadcast composer includes streams based on
625+
* <a href="https://tokbox.com/developer/guides/archive-broadcast-layout/#stream-prioritization-rules">stream
626+
* prioritization rules</a>.</li>
627+
*
601628
* </ul>
602629
*
603630
* @return Broadcast An object with properties defining the broadcast.
@@ -609,14 +636,16 @@ public function startBroadcast(string $sessionId, array $options = []): Broadcas
609636
// not preferred to depend on that in the SDK because its then harder to garauntee backwards
610637
// compatibility
611638
$defaults = array(
612-
'layout' => Layout::getBestFit()
639+
'layout' => Layout::getBestFit(),
640+
'streamMode' => 'auto'
613641
);
614642
$options = array_merge($defaults, $options);
615-
list($layout) = array_values($options);
643+
list($layout, $streamMode) = array_values($options);
616644

617645
// validate arguments
618646
Validators::validateSessionId($sessionId);
619647
Validators::validateLayout($layout);
648+
Validators::validateHasStreamMode($streamMode);
620649

621650
// make API call
622651
$broadcastData = $this->client->startBroadcast($sessionId, $options);

src/OpenTok/StreamMode.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace OpenTok;
4+
5+
use OpenTok\Util\BasicEnum;
6+
7+
/**
8+
* Defines streamMode values that can be used when either starting an Archive or a Broadcast
9+
*/
10+
abstract class StreamMode extends BasicEnum
11+
{
12+
/**
13+
* Default mode, will automatically add all streams to Archive or Broadcast
14+
*/
15+
public const AUTO = 'auto';
16+
17+
/**
18+
* Manual mode, will allow for manual adding and removal of streams for an Archive or Broadcast
19+
*/
20+
public const MANUAL = 'manual';
21+
}

0 commit comments

Comments
 (0)