Node.js Demo App
This is a minimal working example that demonstrates real-time speech translation in a browser.
https://github.com/pinch-eng/pinch-realtime-demo
Quick Start
1. Clone the repository
git clone https://github.com/pinch-eng/pinch-realtime-demo
cd pinch-realtime-demo
2. Install Dependencies
npm install
3. Add Your API Key
Create a .env file in the project root:
PINCH_API_KEY=your_api_key_here
Don’t have an API key? Login to the Pinch Developer Portal >
4. Run the Demo
npm start
You’ll see:
EXAMPLE OUTPUT
Pinch Real-Time Demo running at http://localhost:3000
5. Try It Out
- Open your browser to
http://localhost:3000 - Click the Connect button
- Allow microphone access when prompted
- Start speaking and watch the real-time translation appear!
How It Works
The demo has two simple parts:
Backend (server.js)
- Express server that runs on your computer
- Proxies requests to the Pinch API (keeps your API key secret)
- Serves the HTML file to your browser
Frontend (index.html)
- Single HTML file with embedded JavaScript
- Connects to the translation service
- Captures microphone audio and sends it for translation
- Displays transcripts and plays translated audio
Understanding the Code
Session Creation (Backend)
The backend creates a secure session:
// server.js
app.post("/api/session", async (req, res) => {
const response = await fetch("https://api.startpinch.com/api/beta1/session", {
method: "POST",
headers: {
"Authorization": `Bearer ${PINCH_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
source_language: "en-US",
target_language: "es-ES",
voice_type: "clone"
})
});
const data = await response.json();
res.json(data);
});
Connecting to the Room (Frontend)
// Get credentials from backend
const { url, token } = await fetch("/api/session", {
method: "POST"
}).then(r => r.json());
// Connect to LiveKit room
const room = new Room();
await room.connect(url, token);
// Start streaming microphone
await room.localParticipant.setMicrophoneEnabled(true);
Receiving Transcripts (Frontend)
The browser listens for transcript messages:
room.on(RoomEvent.DataReceived, (payload) => {
const message = JSON.parse(new TextDecoder().decode(payload));
if (message.type === "original_transcript") {
// Display original text in left panel
displayOriginal(message.text, message.is_final);
}
else if (message.type === "translated_transcript") {
// Display translation in right panel
displayTranslated(message.text, message.is_final);
}
});
Receiving Audio (Frontend)
The browser plays translated audio automatically:
room.on(RoomEvent.TrackSubscribed, (track) => {
if (track.kind !== Track.Kind.Audio) return;
// Create audio element
const audioEl = document.createElement("audio");
audioEl.autoplay = true;
audioEl.playsInline = true;
// Attach translated audio stream
track.attach(audioEl);
document.body.appendChild(audioEl);
});
Change Languages
Edit server.js to translate between different languages:
body: JSON.stringify({
source_language: "en-US", // Change this
target_language: "es-ES", // Change this
voice_type: "clone"
})
Check Supported languages > for the full list.