diff --git a/server/php/display.php b/server/php/display.php index 92ba676..ce63225 100644 --- a/server/php/display.php +++ b/server/php/display.php @@ -71,7 +71,6 @@ // Get URL parameters const urlParams = new URLSearchParams(window.location.search); const room = urlParams.get('room') || 'default'; - const passphrase = urlParams.get('passphrase') || ''; const fadeAfter = parseInt(urlParams.get('fade') || '10'); const showTimestamps = urlParams.get('timestamps') !== 'false'; @@ -96,7 +95,7 @@ // Connect to Server-Sent Events function connect() { - const url = `server.php?action=stream&room=${encodeURIComponent(room)}&passphrase=${encodeURIComponent(passphrase)}`; + const url = `server.php?action=stream&room=${encodeURIComponent(room)}`; const eventSource = new EventSource(url); eventSource.onopen = () => { @@ -162,7 +161,7 @@ // Load recent transcriptions on startup async function loadRecent() { try { - const url = `server.php?action=list&room=${encodeURIComponent(room)}&passphrase=${encodeURIComponent(passphrase)}`; + const url = `server.php?action=list&room=${encodeURIComponent(room)}`; const response = await fetch(url); const data = await response.json(); diff --git a/server/php/index.html b/server/php/index.html new file mode 100644 index 0000000..64fcb7c --- /dev/null +++ b/server/php/index.html @@ -0,0 +1,360 @@ + + + + + + Multi-User Transcription Server + + + +
+
+

🎙️ Multi-User Transcription Server

+

Merge captions from multiple streamers into a single OBS display

+
+ +
+ +
+

What is this?

+

This server allows multiple streamers using the Local Transcription app to merge their real-time captions into a single stream. Perfect for collaborative streams, podcasts, or gaming sessions with multiple commentators.

+ +
+
+

🔒 Secure

+

Room-based isolation with passphrase authentication

+
+
+

🎨 Colorful

+

Each user gets a unique color (supports 20+ users)

+
+
+

⚡ Real-time

+

Low-latency streaming via Server-Sent Events

+
+
+

🌐 Universal

+

Works on any standard PHP hosting

+
+
+
+ + +
+

Get Started

+

Click the button below to generate a unique room with random credentials:

+ +
+ + +
+
+

📱 For Desktop App Users

+
Room Name:
+
-
+ + +
Passphrase:
+
-
+ + +
Server URL:
+
-
+ +
+ +
+

📺 For OBS Browser Source

+
Display URL:
+
-
+ + +
+ Note: The display URL does not contain the passphrase for security. Only users with the passphrase can send transcriptions. +
+
+
+
+
+ + +
+

How to Use

+
+
+

Generate Room Credentials

+

Click "Generate New Room" above to create a unique room with a random name and passphrase. Share these with your streaming team.

+
+
+

Configure Desktop App

+

In the Local Transcription app, go to Settings → Server Sync and enter:

+
    +
  • Enable Server Sync: ✓
  • +
  • Server URL: (from above)
  • +
  • Room Name: (from above)
  • +
  • Passphrase: (from above)
  • +
+
+
+

Add to OBS

+

In OBS, add a Browser source and paste the Display URL. Set width to 1920 and height to your preference (e.g., 200-400px).

+
+
+

Start Streaming!

+

All team members start transcription in their apps. Captions from everyone appear merged in OBS with different colors per person.

+
+
+
+ + +
+

Frequently Asked Questions

+ +

How many users can join one room?

+

Technically unlimited, but we've tested up to 20 users successfully. Each user gets a unique color.

+ +

Is my passphrase secure?

+

Yes! Passphrases are hashed using PHP's password_hash() function. They're never stored in plain text.

+ +

How long does a room stay active?

+

Rooms are automatically cleaned up after 2 hours of inactivity to save server resources.

+ +

Can I use custom room names?

+

Yes! You can use any room name you want instead of the randomly generated one. Just make sure all team members use the exact same name.

+
+
+
+ + + + diff --git a/server/php/server.php b/server/php/server.php index d048dfa..941361d 100644 --- a/server/php/server.php +++ b/server/php/server.php @@ -83,18 +83,26 @@ function handleSend() { /** * Handle streaming transcriptions via Server-Sent Events + * Note: Passphrase is optional for streaming (read-only access) */ function handleStream() { // Get parameters $room = sanitize($_GET['room'] ?? ''); - $passphrase = $_GET['passphrase'] ?? ''; - if (empty($room) || empty($passphrase)) { - sendError('Missing room or passphrase', 400); + if (empty($room)) { + sendError('Missing room name', 400); } - if (!verifyPassphrase($room, $passphrase)) { - sendError('Invalid passphrase', 401); + // Passphrase is optional for streaming (read-only) + // If room doesn't exist yet, return empty stream + if (!roomExists($room)) { + // Return empty stream - room doesn't exist yet + header('Content-Type: text/event-stream'); + header('Cache-Control: no-cache'); + header('X-Accel-Buffering: no'); + echo ": waiting for room to be created\n\n"; + flush(); + exit(); } // Set SSE headers @@ -136,19 +144,17 @@ function handleStream() { /** * Handle listing recent transcriptions + * Note: Passphrase is optional for listing (read-only access) */ function handleList() { $room = sanitize($_GET['room'] ?? ''); - $passphrase = $_GET['passphrase'] ?? ''; - if (empty($room) || empty($passphrase)) { - sendError('Missing room or passphrase', 400); - } - - if (!verifyPassphrase($room, $passphrase)) { - sendError('Invalid passphrase', 401); + if (empty($room)) { + sendError('Missing room name', 400); } + // Passphrase is optional for read-only access + // If room doesn't exist, return empty array $transcriptions = getTranscriptions($room); sendJson(['transcriptions' => $transcriptions]); } @@ -235,6 +241,13 @@ function getRoomFile($room) { return STORAGE_DIR . '/room_' . md5($room) . '.json'; } +/** + * Check if room exists + */ +function roomExists($room) { + return file_exists(getRoomFile($room)); +} + /** * Cleanup old sessions */