e6891e81c3
**Overview:** This commit represents a comprehensive refactoring of the application to improve real-time audio streaming capabilities. The key change is the integration of WebRTC for peer-to-peer audio streaming while using Hyperswarm exclusively for signaling. This transition addresses efficiency, reliability, and scalability issues present in the original implementation. **Old Method:** - **Audio Streaming via Hyperswarm Data Channels:** - The original code used Hyperswarm for both signaling and streaming audio data. - Audio data was captured from the microphone, converted to binary, and transmitted over Hyperswarm connections. - Listeners received the audio data chunks and processed them to play back the audio. - **Issues:** - Inefficient for real-time audio streaming due to Hyperswarm's limitations for media data. - Higher latency and potential synchronization problems. - Difficulty managing peer connections and media streams effectively. **New Method:** - **Integration of WebRTC for Audio Streaming:** - Implemented `RTCPeerConnection` instances for efficient, real-time, peer-to-peer audio streaming. - Used Hyperswarm solely for signaling to establish and manage connections. - Audio tracks are now transmitted over WebRTC connections, leveraging optimized protocols for media. - **Benefits:** - Improved audio quality and reduced latency. - Enhanced NAT traversal and firewall compatibility via ICE servers. - Better management of media streams and peer connections. **Key Changes:** 1. **WebRTC Implementation:** - **Broadcaster Side:** - Created `RTCPeerConnection` instances for each listener. - Added local audio tracks from the microphone to the peer connections. - Managed signaling messages (`offer`, `answer`, `candidate`) received via Hyperswarm. - Handled ICE candidate exchange and connection state changes. - **Listener Side:** - Created an `RTCPeerConnection` to connect to the broadcaster. - Added a transceiver with `recvonly` direction to receive audio streams. - Managed signaling messages and ICE candidates. - Played received audio streams using HTML `<audio>` elements. 2. **Signaling via Hyperswarm:** - Utilized Hyperswarm connections for exchanging signaling messages in JSON format. - Messages include `offer`, `answer`, and `candidate` types. - Ensured proper serialization and deserialization of signaling data. 3. **ICE Candidate Handling:** - Implemented ICE candidate queuing to handle candidates arriving before the remote description is set. - Stored incoming ICE candidates in queues and processed them after setting the remote description. - Added detailed logging for ICE candidate exchange and connection states. 4. **Peer Count Accuracy:** - Updated the `updatePeerCount()` function to use `conns.length`, reflecting active Hyperswarm connections. - Ensured the peer count updates immediately when connections are established or closed. - Improved UI feedback regarding the number of connected peers. 5. **Audio Input Switching Without Disconnecting Peers:** - Modified the `applyAudioSource()` function to replace audio tracks in existing peer connections without restarting the station. - Obtained a new audio stream with the selected input device. - Used `RTCRtpSender.replaceTrack()` to update the audio track in each peer connection. - Stopped old audio tracks to free up resources. - Allowed broadcasters to switch microphones seamlessly without interrupting listeners' audio. 6. **Error Handling and Debugging Improvements:** - Added extensive logging throughout the code to trace execution flow and internal state. - Wrapped asynchronous operations in `try...catch` blocks to handle errors gracefully. - Provided informative console messages for successful operations and errors. 7. **User Interface Adjustments:** - Retained existing UI elements and controls. - Updated event listeners to align with the new logic. - Provided real-time updates to station information and peer count. **Benefits of the New Method:** - **Enhanced Audio Quality and Performance:** - Leveraging WebRTC provides better audio streaming capabilities optimized for real-time communication. - Reduced latency and improved synchronization. - **Scalability and Reliability:** - Proper handling of peer connections and media streams improves the application's scalability. - Robust error handling ensures better reliability under various network conditions. - **Improved User Experience:** - Listeners experience uninterrupted audio even when broadcasters change input devices. - Accurate peer count provides broadcasters with immediate feedback on their audience size. **Testing and Verification:** - Tested the application with multiple broadcasters and listeners to ensure proper functionality. - Verified that audio streams initiate correctly and continue even after input device changes. - Confirmed that peer counts update accurately on both broadcaster and listener sides. - Ensured that no errors appear in the console logs during normal operation. |
||
---|---|---|
assets | ||
screenshots | ||
.gitignore | ||
app.js | ||
index.html | ||
package.json | ||
README.md |
pearCast - A Peer-to-Peer Audio Broadcasting App
pearCast
is a decentralized, peer-to-peer (P2P) audio broadcasting application that enables users to broadcast and listen to live audio streams directly from their web browser without relying on centralized servers. Using Hyperswarm for P2P networking and the Web Audio API for audio capture and playback, pearCast
allows users to create and join audio broadcast stations effortlessly.
Run the app on pear!
pear run pear://q3rutpfbtdsr7ikdpntpojcxy5u356qfczzgqomxqk3jdxn6ao8y
Key Features
- Create or Join a Station: Host a broadcast or tune into an existing one.
- Microphone Selection: Broadcasters can select and switch between available audio input devices.
- Real-time Audio Streaming: Capture and stream live audio to all connected listeners.
- Decentralized Networking: Peer-to-peer connections using Hyperswarm, eliminating the need for a centralized server.
- Error Handling: Logs peer disconnections and connection resets without crashing.
Technologies Used
- Hyperswarm: For discovering and connecting peers based on a shared "topic" key, ensuring direct connections without the need for central servers.
- Web Audio API: A powerful API for capturing and processing live audio in the browser, allowing real-time audio streaming.
- Bootstrap: For responsive and user-friendly UI elements.
- JavaScript & Node.js: Application logic, error handling, and P2P networking.
- Pear CLI: Pear CLI.
Table of Contents
Getting Started
Prerequisites
- Node.js: Required to install dependencies and run the app.
- Pear CLI: (Optional) Use the Pear CLI if working with a P2P or desktop runtime.
Installation
-
Clone the Repository:
git clone https://git.ssh.surf/snxraven/pearCast.git cd pearCast
-
Install Dependencies:
npm install
-
Run the App:
pear run --dev .
Note: If you’re not using the Pear CLI, you can serve
index.html
through a local web server (e.g., usingLive Server
extension in VSCode or a simple HTTP server).
User Guide
Creating a Broadcast Station
- Click "Create Station": Initiates a new station and begins capturing audio from the microphone.
- View Station ID: Once created, the station will display a unique ID (based on a cryptographic key), which can be shared with others to join.
- Audio Input Selection: Choose the desired microphone input from a dropdown menu, then click "Apply" to switch.
- Leaving the Broadcast: Click "Leave Broadcast" to end the session, which will also disconnect all connected peers.
Joining a Broadcast Station
- Click "Join Station": Opens a modal window.
- Enter Station ID: Input the ID shared by the broadcaster and click "Join" to connect.
- Listen to Broadcast: Audio from the broadcast will begin streaming in real-time.
- Leaving the Broadcast: The listener can leave the broadcast by closing the connection in the browser or stopping playback.
Changing Audio Input
For Broadcasters Only: Broadcasters can change their microphone input while streaming. Simply select a different device in the "Audio Input Source" dropdown and click "Apply" to switch. The broadcast will automatically start using the newly selected device.
Technical Details
How P2P Connections are Handled
The core networking functionality uses Hyperswarm. Each station (both broadcaster and listener) connects to a unique "topic" based on a cryptographic key. Hyperswarm manages discovery and connection setup without central servers by joining a Distributed Hash Table (DHT). Key components include:
-
Generating a Station ID: When a station is created,
crypto.randomBytes(32)
generates a 32-byte cryptographic key that uniquely identifies the broadcast. Hyperswarm joins this topic in "server mode" for the broadcaster and "client mode" for listeners. -
Peer Connections: Both broadcaster and listener connections are managed by Hyperswarm's
swarm.on('connection')
event, which initiates a stream for sending or receiving audio data. -
Handling Disconnects: Each connection includes error handling and disconnect logging. A connection reset (ECONNRESET) or manual disconnect is logged without crashing the app.
Audio Capture and Streaming
Using the Web Audio API, pearCast
captures and processes audio from the microphone and streams it to connected peers.
-
Audio Context Setup: When a station is created, an
AudioContext
is initialized. This manages audio data flow, including selecting the appropriate microphone input. -
Real-time Audio Processing: Audio is captured as raw data in
Float32Array
format, then buffered and streamed in chunks. The broadcaster'sprocessor.onaudioprocess
event transmits audio data to all connected peers. -
Playback for Listeners: When a listener receives audio data, it’s buffered and played via an
AudioBufferSourceNode
connected to theAudioContext
, enabling real-time audio streaming without delays.
Error Handling and Disconnection Logging
- Graceful Peer Disconnects: Each connection uses an
on('error')
handler that logs disconnect events, preventing crashes from unexpected disconnects (e.g.,ECONNRESET
). - Empty Buffer Signal: To notify listeners that a broadcast has ended, the broadcaster sends an empty buffer to all connected peers before stopping the stream. Listeners handle this signal by stopping playback.
Code Structure
HTML (index.html)
index.html
contains the core layout and UI components:
- Station Controls: Create or join a station and leave the broadcast.
- Audio Input Selection: Available to broadcasters only, allowing them to change input sources.
- Bootstrap Modal: Provides a user-friendly modal interface for joining a station with a specific ID.
JavaScript (app.js)
app.js
contains the main application logic:
- Station Management: Functions to create or join stations, handle connections, and manage disconnects.
- Audio Capture & Processing: Configures audio context, captures microphone data, and processes audio buffers.
- Error Handling: Includes connection reset handling and graceful disconnect logging.
- Audio Source Selection: Enables broadcasters to choose from available audio input devices.
Example Screenshots
Feature | Screenshot |
---|---|
Create Station | |
Join Station Modal | |
Audio Input Control |
Troubleshooting
-
Connection Reset Errors:
- If you encounter
ECONNRESET
errors, they are logged as peer disconnections. Check if a peer has disconnected unexpectedly.
- If you encounter
-
No Audio Device Detected:
- Ensure your browser has permission to access the microphone, and refresh the device list if necessary.
-
Audio Source Changes Not Applying:
- If changing the audio input source doesn't take effect, ensure you click "Apply" after selecting the device.