Skip to content

Commit c326ef4

Browse files
committed
use new webrtc server --- support iphone
1 parent f7953ea commit c326ef4

4 files changed

Lines changed: 264 additions & 221 deletions

File tree

README.md

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@ SmartMicrophone is a modern, open-source web-based microphone and remote control
1616

1717
---
1818

19-
## Bugs
20-
- **No iPhone Support:** for some reason webrtc-cli does not like webrtc streams from iphones. Currently Android and Linux clients work.
21-
2219
## Installation
2320
git clone https://github.com/dgruss/SmartMicrophone.git
2421
### Supported OS: Ubuntu/Debian (recommended)
@@ -27,18 +24,14 @@ git clone https://github.com/dgruss/SmartMicrophone.git
2724
```sh
2825
sudo add-apt-repository ppa:longsleep/golang-backports
2926
sudo apt update
30-
sudo apt update
31-
sudo apt install python3 python3-pip git make gcc make pkg-config libopus-dev libopusfile-dev libpulse-dev golang-go libsdl2-image-dev python3-flask pipewire pipewire-pulse
27+
sudo apt install python3 python3-pip git make gcc make pkg-config libopus-dev libopusfile-dev libpulse-dev golang-go libsdl2-image-dev python3-flask pipewire pipewire-pulse libpulse-dev libopus-dev
3228
```
3329

34-
#### 2. Clone the Repository, Submodules, and build webrtc-cli
30+
#### 2. Clone the Repository, Submodules, and build pulse-receive
3531
```sh
3632
git clone https://github.com/dgruss/SmartMicrophone.git
37-
cd SmartMicrophone
38-
git submodule init
39-
git submodule update
40-
cd webrtc-cli
41-
make
33+
cd SmartMicrophone/pulse-receive
34+
go build .
4235
cd ..
4336
```
4437

@@ -47,6 +40,17 @@ cd ..
4740
- Some features require using [the dgruss beta3](https://github.com/dgruss/USDX/tree/beta3) version as they are not upstreamed yet
4841
- Make sure you know the path to your usdx directory (e.g., `/home/user/usdx`)
4942

43+
```
44+
cd ~
45+
git clone https://github.com/dgruss/USDX.git usdx
46+
cd usdx
47+
git checkout beta3
48+
sudo apt install git automake make gcc fpc libsdl2-image-dev libavformat-dev libavcodec-dev libavutil-dev libswresample-dev libswscale-dev libsqlite3-dev libfreetype6-dev portaudio19-dev libportmidi-dev liblua5.3-dev libopencv-videoio-dev fonts-dejavu
49+
./autogen.sh
50+
./configure --without-portaudio --without-portmixer
51+
make
52+
```
53+
5054
#### 4. (Optional) Configure SSL, Set up Wi-Fi Hotspot and Internet Forwarding
5155
- Place your SSL certificate and key files in the project directory if you want HTTPS --- this might be required to convince your phone to use WebRTC. Self-signed certificates work. Otherwise you can use a domain or subdomain you have on the Internet (give the DNS entry a short lifetime on your server!) and configure SmartMicrophone to use domain and certificates
5256
- See Advanced Networking below for details

server.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ def gen():
119119

120120
return Response(stream_with_context(gen()), mimetype='text/event-stream')
121121

122-
123122
# Endpoint that merges rooms and control status and records a heartbeat
124123
@app.route('/status', methods=['GET'])
125124
def status():
@@ -138,6 +137,9 @@ def status():
138137
@app.before_request
139138
def log_incoming_request():
140139
try:
140+
sid = session.get('session_id')
141+
if sid:
142+
LAST_SEEN[sid] = time.time()
141143
if not request.path in ['/rooms', '/status', '/control/status']:
142144
logger.info('Incoming request: %s %s args=%s', request.method, request.path, dict(request.args))
143145
except Exception:
@@ -157,7 +159,7 @@ def index():
157159
# maybe this person just reloaded but still has a microphone running
158160
if 'session_id' in session and is_youngest_session():
159161
mic_idx = session.get('microphone_index')
160-
logger.info("Session %s is still active, automatically reconnecting microphone %s.", session.get('session_id'), mic_idx)
162+
logger.debug("Session %s is still active, automatically reconnecting microphone %s.", session.get('session_id'), mic_idx)
161163
# only reconnect automatically if we actually have a microphone index in the session
162164
if mic_idx is not None:
163165
automatically_reconnect = True
@@ -183,8 +185,9 @@ def api():
183185
action = request.form.get('action')
184186
logger.info(f'Received action: {action}')
185187

188+
186189
if action == 'start_webrtc':
187-
# Start per-player webrtc-cli using the provided SDP offer
190+
# Start per-player pulse-receive using the provided SDP offer
188191
offer = request.form.get('offer')
189192
if not offer:
190193
return jsonify({'success': False, 'error': 'Missing offer'})
@@ -213,9 +216,6 @@ def api():
213216
'microphone_start_timestamp': session['microphone_start_timestamp']
214217
}
215218

216-
return jsonify({'success': True, 'answer': start_res.get('answer'), 'player_id': player_id})
217-
218-
219219
if action == 'get_assignments':
220220
return jsonify({'success': True, 'assignments': get_mic_assignments()})
221221

@@ -301,7 +301,7 @@ def run_xdotool_command(args):
301301
ids = [l.strip() for l in ws.stdout.splitlines() if l.strip()]
302302
if ids:
303303
ULTRASTAR_WINDOW_ID = ids[0]
304-
logger.info('Cached UltraStar window id: %s', ULTRASTAR_WINDOW_ID)
304+
logger.debug('Cached UltraStar window id: %s', ULTRASTAR_WINDOW_ID)
305305
else:
306306
logger.warning('No UltraStar window found via `xdotool search UltraStar`')
307307
return False, 'window not found'
@@ -385,7 +385,7 @@ def control_release():
385385
CONTROL_OWNER = None
386386
CONTROL_OWNER_NAME = None
387387
CONTROL_TIMESTAMP = 0
388-
logger.info('Control released by session %s', sid)
388+
logger.debug('Control released by session %s', sid)
389389
return jsonify({'success': True})
390390

391391

@@ -1227,6 +1227,20 @@ def stale_cleanup_loop():
12271227
stale = []
12281228
for sid, last in list(LAST_SEEN.items()):
12291229
if now - last > 10.0:
1230+
# If this session has an associated microphone process that is still alive,
1231+
# treat the session as active and skip stale removal.
1232+
try:
1233+
mic = mgr.microphones.get(sid)
1234+
if mic:
1235+
try:
1236+
if mic.is_process_alive():
1237+
logger.debug('Session %s has active microphone; skipping stale removal', sid)
1238+
continue
1239+
except Exception:
1240+
# If mic liveness check fails, fall back to treating as stale
1241+
logger.exception('Error checking mic liveness for session %s', sid)
1242+
except Exception:
1243+
logger.exception('Error inspecting microphones for session %s', sid)
12301244
stale.append(sid)
12311245
for sid in stale:
12321246
try:

static/script.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -735,9 +735,9 @@ document.addEventListener('DOMContentLoaded', function() {
735735
const pc = new RTCPeerConnection();
736736
window.smartMicPC = pc;
737737

738-
// Send local ICE candidates to server if needed (server-side webrtc-cli may not need them)
738+
// Send local ICE candidates to server if needed (server-side pulse-receive may not need them)
739739
pc.onicecandidate = (ev) => {
740-
// we do not currently send candidates to server; server's webrtc-cli is expected to be
740+
// we do not currently send candidates to server; server's pulse-receive is expected to be
741741
// the offer/answer terminator. If needed, implement trickle ICE here.
742742
if (!ev.candidate) return;
743743
printLog('Local ICE candidate: ' + JSON.stringify(ev.candidate));

0 commit comments

Comments
 (0)