Skip to content

Commit d0575ee

Browse files
authored
Merge pull request #86 from millicast/develop
Release v0.1.8
2 parents 8d25f9b + bc2c0a1 commit d0575ee

19 files changed

+260
-36
lines changed

README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ You will need a Millicast account and a valid publishing token that you can find
4040
```javascript
4141
import { Director, Publish } from '@millicast/sdk'
4242
//Define callback for generate new tokens
43-
const tokenGenerator = () => Director.getPublisher('my-publishing-token', 'my-stream-name')
43+
const tokenGenerator = () => Director.getPublisher({
44+
token: 'my-publishing-token',
45+
streamName: 'my-stream-name'
46+
})
4447

4548
//Create a new instance
4649
const millicastPublish = new Publish(streamName, tokenGenerator)
@@ -85,7 +88,10 @@ import { Director, View } from '@millicast/sdk'
8588
const video = document.getElementById('my-video')
8689

8790
//Define callback for generate new token
88-
const tokenGenerator = () => Director.getSubscriber('my-stream-name', 'my-account-id')
91+
const tokenGenerator = () => Director.getSubscriber({
92+
streamName: 'my-stream-name',
93+
streamAccountId: 'my-account-id'
94+
})
8995

9096
//Create a new instance
9197
const millicastView = new View(streamName, tokenGenerator, video)

packages/millicast-sdk/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/millicast-sdk/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@millicast/sdk",
3-
"version": "0.1.7",
3+
"version": "0.1.8",
44
"description": "SDK for building a realtime broadcaster using the Millicast platform.",
55
"keywords": [
66
"sdk",

packages/millicast-sdk/src/Director.js

Lines changed: 63 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import axios from 'axios'
2-
import jwtDecode from 'jwt-decode'
32
import Logger from './Logger'
43

54
const logger = Logger.get('Director')
@@ -15,7 +14,20 @@ let apiEndpoint = defaultApiEndpoint
1514
* @typedef {Object} MillicastDirectorResponse
1615
* @property {Array<String>} urls - WebSocket available URLs.
1716
* @property {String} jwt - Access token for signaling initialization.
18-
* @property {Object} jwtDecoded - Access token decoded.
17+
*/
18+
19+
/**
20+
* @typedef {Object} DirectorPublisherOptions
21+
* @property {String} token - Millicast Publishing Token.
22+
* @property {String} streamName - Millicast Stream Name.
23+
* @property {("WebRtc" | "Rtmp")} [streamType] - Millicast Stream Type.
24+
*/
25+
26+
/**
27+
* @typedef {Object} DirectorSubscriberOptions
28+
* @property {String} streamName - Millicast publisher Stream Name.
29+
* @property {String} streamAccountId - Millicast Account ID.
30+
* @property {String} [subscriberToken] - Token to subscribe to secure streams. If you are subscribing to an unsecure stream, you can omit this param.
1931
*/
2032

2133
/**
@@ -49,18 +61,18 @@ export default class Director {
4961

5062
/**
5163
* Get publisher connection data.
52-
* @param {String} token - Millicast Publishing Token.
53-
* @param {String} streamName - Millicast Stream Name.
54-
* @param {("WebRtc" | "Rtmp")} [streamType] - Millicast Stream Type.
64+
* @param {DirectorPublisherOptions | String} options - Millicast options or *Deprecated Millicast Publishing Token.*
65+
* @param {String} [streamName] - *Deprecated, use options parameter instead* Millicast Stream Name.
66+
* @param {("WebRtc" | "Rtmp")} [streamType] - *Deprecated, use options parameter instead* Millicast Stream Type.
5567
* @returns {Promise<MillicastDirectorResponse>} Promise object which represents the result of getting the publishing connection path.
56-
* @example const response = await Director.getPublisher(token, streamName)
68+
* @example const response = await Director.getPublisher(options)
5769
* @example
5870
* import { Publish, Director } from '@millicast/sdk'
5971
*
6072
* //Define getPublisher as callback for Publish
6173
* const streamName = "My Millicast Stream Name"
6274
* const token = "My Millicast publishing token"
63-
* const tokenGenerator = () => Director.getPublisher(token, streamName)
75+
* const tokenGenerator = () => Director.getPublisher({token, streamName})
6476
*
6577
* //Create a new instance
6678
* const millicastPublish = new Publish(streamName, tokenGenerator)
@@ -77,15 +89,16 @@ export default class Director {
7789
* await millicastPublish.connect(broadcastOptions)
7890
*/
7991

80-
static async getPublisher (token, streamName, streamType = streamTypes.WEBRTC) {
81-
logger.info('Getting publisher connection path for stream name: ', streamName)
82-
const payload = { streamName, streamType }
83-
const headers = { Authorization: `Bearer ${token}` }
92+
static async getPublisher (options, streamName = null, streamType = streamTypes.WEBRTC) {
93+
const optionsParsed = getPublisherOptions(options, streamName, streamType)
94+
logger.info('Getting publisher connection path for stream name: ', optionsParsed.streamName)
95+
const payload = { streamName: optionsParsed.streamName, streamType: optionsParsed.streamType }
96+
const headers = { Authorization: `Bearer ${optionsParsed.token}` }
8497
const url = `${this.getEndpoint()}/api/director/publish`
8598
try {
8699
const { data } = await axios.post(url, payload, { headers })
87100
logger.debug('Getting publisher response: ', data)
88-
return { ...data.data, jwtDecoded: jwtDecode(data.data.jwt).millicast }
101+
return data.data
89102
} catch (e) {
90103
logger.error('Error while getting publisher connection path: ', e.response?.data)
91104
throw e
@@ -94,20 +107,20 @@ export default class Director {
94107

95108
/**
96109
* Get subscriber connection data.
97-
* @param {String} streamName - Millicast publisher Stream Name.
98-
* @param {String} streamAccountId - Millicast Account ID.
99-
* @param {String} [subscriberToken] - Token to subscribe to secure streams. If you are subscribing to an unsecure stream, you can omit this param.
110+
* @param {DirectorSubscriberOptions | String} options - Millicast options or *Deprecated Millicast publisher Stream Name.*
111+
* @param {String} [streamAccountId] - *Deprecated, use options parameter instead* Millicast Account ID.
112+
* @param {String} [subscriberToken] - *Deprecated, use options parameter instead* Token to subscribe to secure streams. If you are subscribing to an unsecure stream, you can omit this param.
100113
* @returns {Promise<MillicastDirectorResponse>} Promise object which represents the result of getting the subscribe connection data.
101-
* @example const response = await Director.getSubscriber(streamName, streamAccountId)
114+
* @example const response = await Director.getSubscriber(options)
102115
* @example
103116
* import { View, Director } from '@millicast/sdk'
104117
*
105118
* //Define getSubscriber as callback for Subscribe
106119
* const streamName = "My Millicast Stream Name"
107120
* const accountId = "Millicast Publisher account Id"
108-
* const tokenGenerator = () => Director.getSubscriber(streamName, accountId)
121+
* const tokenGenerator = () => Director.getSubscriber({streamName, accountId})
109122
* //... or for an secure stream
110-
* const tokenGenerator = () => Director.getSubscriber(streamName, accountId, '176949b9e57de248d37edcff1689a84a047370ddc3f0dd960939ad1021e0b744')
123+
* const tokenGenerator = () => Director.getSubscriber({streamName, accountId, subscriberToken: '176949b9e57de248d37edcff1689a84a047370ddc3f0dd960939ad1021e0b744'})
111124
*
112125
* //Create a new instance
113126
* const millicastView = new View(streamName, tokenGenerator)
@@ -125,21 +138,47 @@ export default class Director {
125138
* await millicastView.connect(options)
126139
*/
127140

128-
static async getSubscriber (streamName, streamAccountId, subscriberToken = null) {
129-
logger.info(`Getting subscriber connection data for stream name: ${streamName} and account id: ${streamAccountId}`)
130-
const payload = { streamAccountId, streamName }
141+
static async getSubscriber (options, streamAccountId = null, subscriberToken = null) {
142+
const optionsParsed = getSubscriberOptions(options, streamAccountId, subscriberToken)
143+
logger.info(`Getting subscriber connection data for stream name: ${optionsParsed.streamName} and account id: ${optionsParsed.streamAccountId}`)
144+
145+
const payload = { streamAccountId: optionsParsed.streamAccountId, streamName: optionsParsed.streamName }
131146
let headers = {}
132-
if (subscriberToken) {
133-
headers = { Authorization: `Bearer ${subscriberToken}` }
147+
if (optionsParsed.subscriberToken) {
148+
headers = { Authorization: `Bearer ${optionsParsed.subscriberToken}` }
134149
}
135150
const url = `${this.getEndpoint()}/api/director/subscribe`
136151
try {
137152
const { data } = await axios.post(url, payload, { headers })
138153
logger.debug('Getting subscriber response: ', data)
139-
return { ...data.data, jwtDecoded: jwtDecode(data.data.jwt).millicast }
154+
return data.data
140155
} catch (e) {
141156
logger.error('Error while getting subscriber connection path: ', e.response?.data)
142157
throw e
143158
}
144159
}
145160
}
161+
162+
const getPublisherOptions = (options, legacyStreamName, legacyStreamType) => {
163+
let parsedOptions = (typeof options === 'object') ? options : {}
164+
if (Object.keys(parsedOptions).length === 0) {
165+
parsedOptions = {
166+
token: options,
167+
streamName: legacyStreamName,
168+
streamType: legacyStreamType
169+
}
170+
}
171+
return parsedOptions
172+
}
173+
174+
const getSubscriberOptions = (options, legacyStreamAccountId, legacySubscriberToken) => {
175+
let parsedOptions = (typeof options === 'object') ? options : {}
176+
if (Object.keys(parsedOptions).length === 0) {
177+
parsedOptions = {
178+
streamName: options,
179+
streamAccountId: legacyStreamAccountId,
180+
subscriberToken: legacySubscriberToken
181+
}
182+
}
183+
return parsedOptions
184+
}

packages/millicast-sdk/src/PeerConnection.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ export default class PeerConnection extends EventEmitter {
212212
}
213213

214214
logger.info('Updating bitrate to value: ', bitrate)
215-
this.peer = await this.getRTCPeer()
215+
this.sessionDescription = await this.peer.createOffer()
216216
await this.peer.setLocalDescription(this.sessionDescription)
217217
const sdp = this.updateBandwidthRestriction(this.peer.remoteDescription.sdp, bitrate)
218218
await this.setRTCRemoteSDP(sdp)

packages/millicast-sdk/src/Publish.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import jwtDecode from 'jwt-decode'
12
import reemit from 're-emitter'
23
import Logger from './Logger'
34
import BaseWebRTC from './utils/BaseWebRTC'
@@ -103,6 +104,11 @@ export default class Publish extends BaseWebRTC {
103104
logger.error('Error while broadcasting. Publisher data required')
104105
throw new Error('Publisher data required')
105106
}
107+
const recordingAvailable = jwtDecode(publisherData.jwt).millicast.record
108+
if (this.options.record && !recordingAvailable) {
109+
logger.error('Error while broadcasting. Record option detected but recording is not available')
110+
throw new Error('Record option detected but recording is not available')
111+
}
106112
this.signaling = new Signaling({
107113
streamName: this.streamName,
108114
url: `${publisherData.urls[0]}?token=${publisherData.jwt}`

packages/millicast-sdk/src/utils/BaseWebRTC.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ export default class BaseWebRTC extends EventEmitter {
4848
this.options = null
4949
}
5050

51+
/**
52+
* Get current RTC peer connection.
53+
* @returns {RTCPeerConnection} Object which represents the RTCPeerConnection.
54+
*/
55+
getRTCPeerConnection () {
56+
return this.webRTCPeer ? this.webRTCPeer.getRTCPeer() : null
57+
}
58+
5159
/**
5260
* Stops connection.
5361
*/
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Feature: As a user I want to get the peer so I can use it
2+
3+
Scenario: Get existing RTC peer
4+
Given I have a BaseWebRTC instanced and existing peer
5+
When I want to get the peer
6+
Then returns the peer
7+
8+
Scenario: Get no existing RTC peer
9+
Given I have a BaseWebRTC instanced and no existing peer
10+
When I want to get the peer
11+
Then returns null

packages/millicast-sdk/tests/features/GetPublisherConnectionPath.feature

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,9 @@ Feature: As a user I want to publish to a Millicast Stream so I can get a connec
1818
Scenario: Publish with an existing stream name and valid token using other API Endpoint
1919
Given I have a valid token and an existing stream name
2020
When I request a connection path to Director API
21+
Then I get the publish connection path
22+
23+
Scenario: Publish with an existing stream name, valid token and options as object
24+
Given I have a valid token and an existing stream name
25+
When I request a connection path to Director API using options object
2126
Then I get the publish connection path

packages/millicast-sdk/tests/features/GetSubscriberConnectionPath.feature

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,9 @@ Feature: As a user I want to subscribe to a Millicast Stream so I can get a conn
1818
Scenario: Subscribe to an existing stream using other API Endpoint
1919
Given I have an existing stream name, accountId and no token
2020
When I request a connection path to Director API
21+
Then I get the subscriber connection path
22+
23+
Scenario: Subscribe to an existing unrestricted stream, valid accountId, no token and options as object
24+
Given I have an existing stream name, accountId and no token
25+
When I request a connection path to Director API using options object
2126
Then I get the subscriber connection path

0 commit comments

Comments
 (0)