Skip to content

Commit

Permalink
Feat/space backup (#746)
Browse files Browse the repository at this point in the history
* refactor: added code for joining livekit room for listeners (#731)

* feat: drop in livekit inplace of livepeer (#736)

* feat: drop in livekit inplace of livepeer

* feat: added microphone

* feat: added mic

* feat: added access control

---------

Co-authored-by: Nilesh Gupta <[email protected]>
  • Loading branch information
arn4b and 0xNilesh authored Oct 3, 2023
1 parent ec08686 commit f64b275
Show file tree
Hide file tree
Showing 12 changed files with 521 additions and 173 deletions.
20 changes: 10 additions & 10 deletions packages/restapi/src/lib/space/acceptPromotionRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ export async function acceptPromotionRequest(
});

// accept the promotion request
this.acceptRequest({
signalData,
senderAddress: this.data.local.address,
recipientAddress: pCAIP10ToWallet(promoteeAddress),
chatId: spaceId,
details: {
type: SPACE_ACCEPT_REQUEST_TYPE.ACCEPT_PROMOTION,
data: {},
},
});
// this.acceptRequest({
// signalData,
// senderAddress: this.data.local.address,
// recipientAddress: pCAIP10ToWallet(promoteeAddress),
// chatId: spaceId,
// details: {
// type: SPACE_ACCEPT_REQUEST_TYPE.ACCEPT_PROMOTION,
// data: {},
// },
// });
}
217 changes: 109 additions & 108 deletions packages/restapi/src/lib/space/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@ type StartType = {
livepeerApiKey: string;
};

export async function start(this: Space, options: StartType): Promise<void> {
const { livepeerApiKey } = options || {};
// export async function start(this: Space, options: StartType): Promise<void> {
export async function start(this: Space): Promise<void> {
// const { livepeerApiKey } = options || {};

try {
// host should have there audio stream
if (!this.data.local.stream) {
throw new Error('Local audio stream not found');
}
// if (!this.data.local.stream) {
// throw new Error('Local audio stream not found');
// }

const space = await get({
spaceId: this.spaceSpecificData.spaceId,
Expand Down Expand Up @@ -115,109 +116,109 @@ export async function start(this: Space, options: StartType): Promise<void> {
});
});

// start the livepeer playback and store the playback URL group meta
// send a notification/meta message to all the added listeners (members) telling the space has started

// create the mergeStream object
const mergedStream = getMergeStreamObject(this.data.local.stream);
// store the mergeStreamObject
this.mergedStream = mergedStream;

const url = 'https://livepeer.studio/api/stream';
const data = {
name: this.spaceSpecificData.spaceName,
record: true,
};

const { data: responseData } = await axios.post(url, data, {
headers: {
Authorization: 'Bearer ' + livepeerApiKey,
},
});

const { streamKey, playbackId } = responseData;

console.log('livepeer details', streamKey, playbackId);

this.update({ meta: playbackId });

let redirectUrl;
try {
console.log('Ignore the following error');

// the redirect URL from the above GET request
await axios.get(`https://livepeer.studio/webrtc/${streamKey}`);
} catch (err: any) {
console.log('redirectUrl error', err);
redirectUrl = err.request.responseURL;
}

// we use the host from the redirect URL in the ICE server configuration
const host = new URL(redirectUrl).host;

const iceServers = [
{
urls: `stun:${host}`,
},
{
urls: `turn:${host}`,
username: 'livepeer',
credential: 'livepeer',
},
];

const peerConnection = new RTCPeerConnection({ iceServers });

const newAudioTrack = mergedStream.result?.getAudioTracks?.()?.[0] ?? null;

if (newAudioTrack) {
peerConnection?.addTransceiver(newAudioTrack, {
direction: 'sendonly',
});
}

/**
* https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createOffer
* We create an SDP offer here which will be shared with the server
*/
const offer = await peerConnection.createOffer();
/** https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setLocalDescription */
await peerConnection.setLocalDescription(offer);

/** Wait for ICE gathering to complete */
const ofr = await new Promise<RTCSessionDescription | null>((resolve) => {
/** Wait at most five seconds for ICE gathering. */
setTimeout(() => {
resolve(peerConnection.localDescription);
}, 5000);
peerConnection.onicegatheringstatechange = (_ev) => {
if (peerConnection.iceGatheringState === 'complete') {
resolve(peerConnection.localDescription);
}
};
});
if (!ofr) {
throw Error('failed to gather ICE candidates for offer');
}
/**
* This response contains the server's SDP offer.
* This specifies how the client should communicate,
* and what kind of media client and server have negotiated to exchange.
*/
const sdpResponse = await fetch(redirectUrl, {
method: 'POST',
mode: 'cors',
headers: {
'content-type': 'application/sdp',
},
body: ofr.sdp,
});
if (sdpResponse.ok) {
const answerSDP = await sdpResponse.text();
await peerConnection.setRemoteDescription(
new RTCSessionDescription({ type: 'answer', sdp: answerSDP })
);
}
// // start the livepeer playback and store the playback URL group meta
// // send a notification/meta message to all the added listeners (members) telling the space has started

// // create the mergeStream object
// const mergedStream = getMergeStreamObject(this.data.local.stream);
// // store the mergeStreamObject
// this.mergedStream = mergedStream;

// const url = 'https://livepeer.studio/api/stream';
// const data = {
// name: this.spaceSpecificData.spaceName,
// record: true,
// };

// const { data: responseData } = await axios.post(url, data, {
// headers: {
// Authorization: 'Bearer ' + livepeerApiKey,
// },
// });

// const { streamKey, playbackId } = responseData;

// console.log('livepeer details', streamKey, playbackId);

// this.update({ meta: playbackId });

// let redirectUrl;
// try {
// console.log('Ignore the following error');

// // the redirect URL from the above GET request
// await axios.get(`https://livepeer.studio/webrtc/${streamKey}`);
// } catch (err: any) {
// console.log('redirectUrl error', err);
// redirectUrl = err.request.responseURL;
// }

// // we use the host from the redirect URL in the ICE server configuration
// const host = new URL(redirectUrl).host;

// const iceServers = [
// {
// urls: `stun:${host}`,
// },
// {
// urls: `turn:${host}`,
// username: 'livepeer',
// credential: 'livepeer',
// },
// ];

// const peerConnection = new RTCPeerConnection({ iceServers });

// const newAudioTrack = mergedStream.result?.getAudioTracks?.()?.[0] ?? null;

// if (newAudioTrack) {
// peerConnection?.addTransceiver(newAudioTrack, {
// direction: 'sendonly',
// });
// }

// /**
// * https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createOffer
// * We create an SDP offer here which will be shared with the server
// */
// const offer = await peerConnection.createOffer();
// /** https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setLocalDescription */
// await peerConnection.setLocalDescription(offer);

// /** Wait for ICE gathering to complete */
// const ofr = await new Promise<RTCSessionDescription | null>((resolve) => {
// /** Wait at most five seconds for ICE gathering. */
// setTimeout(() => {
// resolve(peerConnection.localDescription);
// }, 5000);
// peerConnection.onicegatheringstatechange = (_ev) => {
// if (peerConnection.iceGatheringState === 'complete') {
// resolve(peerConnection.localDescription);
// }
// };
// });
// if (!ofr) {
// throw Error('failed to gather ICE candidates for offer');
// }
// /**
// * This response contains the server's SDP offer.
// * This specifies how the client should communicate,
// * and what kind of media client and server have negotiated to exchange.
// */
// const sdpResponse = await fetch(redirectUrl, {
// method: 'POST',
// mode: 'cors',
// headers: {
// 'content-type': 'application/sdp',
// },
// body: ofr.sdp,
// });
// if (sdpResponse.ok) {
// const answerSDP = await sdpResponse.text();
// await peerConnection.setRemoteDescription(
// new RTCSessionDescription({ type: 'answer', sdp: answerSDP })
// );
// }

console.log('Live Stream started');
} catch (err) {
Expand Down
6 changes: 5 additions & 1 deletion packages/uiweb/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
"registry": "https://registry.npmjs.org/"
},
"dependencies": {
"@livekit/components-react": "^1.2.2",
"@livekit/components-styles": "^1.0.6",
"@livepeer/react": "^2.6.0",
"@pushprotocol/socket": "^0.5.0",
"@unstoppabledomains/resolution": "^8.5.0",
Expand All @@ -20,10 +22,12 @@
"font-awesome": "^4.7.0",
"gif-picker-react": "^1.1.0",
"html-react-parser": "^1.4.13",
"livekit-client": "^1.13.3",
"moment": "^2.29.4",
"react-icons": "^4.10.1",
"react-toastify": "^9.1.3",
"react-twitter-embed": "^4.0.4"
"react-twitter-embed": "^4.0.4",
"uuid": "^9.0.1"
},
"peerDependencies": {
"@pushprotocol/restapi": "^1.2.15",
Expand Down
Loading

0 comments on commit f64b275

Please sign in to comment.