I would like to try to create 2 HTML pages that exchange data between them, one transmits the audio, while the other receives the audio and plays it in the second HTML page, without using an actual server.
I tried to look online, but I didn't understand much 🫥
I believe you want to create two HTML pages where one is the sender
and the other is the receiver
.Do you want to add the audio files as a media embedding or you want to initiate your device's microphone for audio recording.
As you mentioned, you may not need an actual server as you can just set up a webRTC API (web Real Time Communication) that allows you establish a peer-to-peer communication between the two HTML pages. The most commonly used protocol for this is the ICE
protocol (Interactive Connectivity Establishment).
Let me share an example of how you can set up the sender
and receiver
HTML pages.
Create a sender.html
file as shown below:
<body>
<audio id="local" autoplay muted></audio>
<button onclick="start(this)">Start Audio</button>
<button id="stream" onclick="stream(this)" disabled>Broadcast Audio</button>
<script>
// get audio elements
const local = document.querySelector("audio#local");
let peerConnection;
const channel = new BroadcastChannel("stream-audio");
channel.onmessage = e => {
if (e.data.type === "icecandidate") {
peerConnection?.addIceCandidate(e.data.candidate);
} else if (e.data.type === "answer") {
peerConnection?.setRemoteDescription(e.data);
}
}
// functon to start the audio and ask for permission to access microphone
const start = async (e) => {
e.disabled = true;
document.getElementById("stream").disabled = false; // enable the stream button
await navigator.mediaDevices.getUserMedia({ audio: true })
.then((stream) => local.srcObject = stream);
}
const stream = async (e) => {
e.disabled = true;
const config = {};
peerConnection = new RTCPeerConnection(config); // local peer connection
// add an ice candidate event listener,
peerConnection.addEventListener("icecandidate", e => {
let candidate = null;
// prepare a candidate object
if (e.candidate !== null) {
candidate = {
candidate: e.candidate.candidate,
sdpMid: e.candidate.sdpMid,
sdpMLineIndex: e.candidate.sdpMLineIndex,
};
}
channel.postMessage({ type: "icecandidate", candidate });
});
// add media tracks to the peer connection
await local.srcObject.getTracks()
.forEach(track => peerConnection.addTrack(track, local.srcObject));
// Create an offer and send through the browser channel, this is necessary to establish a connection (handshake)
peerConnection.createOffer({ offerToReceiveAudio: true })
.then(async offer => {
await peerConnection.setLocalDescription(offer);
channel.postMessage({ type: "offer", sdp: offer.sdp });
});
}
</script>
</body>
Create a receiver.html
file as shown below:
<body>
<audio id="remote" controls></audio>
<script>
// get audio elements
const remote = document.querySelector("audio#remote");
let peerConnection;
const channel = new BroadcastChannel("stream-audio");
channel.onmessage = e => {
if (e.data.type === "icecandidate") {
peerConnection?.addIceCandidate(e.data.candidate)
} else if (e.data.type === "offer") {
handleOffer(e.data)
}
}
const handleOffer = async (offer) =>{
const config = {};
peerConnection = new RTCPeerConnection(config);
peerConnection.addEventListener("track", e => remote.srcObject = e.streams[0]);
peerConnection.addEventListener("icecandidate", e => {
let candidate = null;
if (e.candidate !== null) {
candidate = {
candidate: e.candidate.candidate,
sdpMid: e.candidate.sdpMid,
sdpMLineIndex: e.candidate.sdpMLineIndex,
}
}
channel.postMessage({ type: "icecandidate", candidate })
});
await peerConnection.setRemoteDescription(offer)
.then(() => peerConnection.createAnswer())
.then(async answer => {
await peerConnection.setLocalDescription(answer);
channel.postMessage({
type: "answer",
sdp: answer.sdp,
});
});
}
</script>
</body>
Create both of these html file and open to the sender.html
page. Start the audio and broadcast the audio from that html page. Open the receiver.html
file on another window or page on the same browser.
I hope I have been able to help!