AI-translated from English; not yet reviewed by a fluent editor.
# OpenAI Realtime দিয়ে স্থানীয় ব্রাউজারে কণ্ঠের কথোপকথন তৈরি করুন
> WebRTC-তে OpenAI Realtime দিয়ে ব্রাউজারের মাইক্রোফোনের স্থানীয় কথোপকথন তৈরি করুন। সম্পূর্ণ সার্ভার ও পেজ কোড API key সার্ভারে রাখে এবং শব্দ পরীক্ষা, মাইক্রোফোন থামানো ও ব্যর্থতা সামলানো দেখায়।
By BIG CHANGE Editorial
Published: 2026-10-19T19:20:34.863Z
Updated: 2026-10-19T19:20:34.863Z
Canonical: https://bigchange.ai/blog/openai-realtime-browser-voice-webrtc-guide

AI-generated conceptual illustration by BIG CHANGE; no actual OpenAI interface, browser test or heard reply is depicted.
OpenAI Realtime API ব্রাউজারকে WebRTC দিয়ে মাইক্রোফোনের শব্দ পাঠাতে এবং কথিত উত্তর বাজাতে দেয়। এই নির্দেশিকা `gpt-realtime-2.1` দিয়ে একটি স্থানীয় কথোপকথন তৈরি করে। API key আপনার কম্পিউটারের Node সার্ভারে থাকে। মডেলে প্রবেশাধিকার ও billing-সহ OpenAI API project চাই; ChatGPT subscription API ব্যবহারের খরচ দেয় না। BIG CHANGE বর্তমান নথি ও নমুনা কোড পরীক্ষা করেছে, কিন্তু অর্থপ্রদত্ত session খোলেনি বা উত্তর শোনেনি।
## বড় পরিবর্তন
- **কী বদলেছে:** OpenAI সরাসরি Realtime কথোপকথনের জন্য ব্রাউজার WebRTC পথ নথিভুক্ত করেছে। স্থানীয় সার্ভার project key রেখে ব্রাউজারের connection offer-এর বদলে answer আনে।
- **কেন গুরুত্বপূর্ণ:** বড় কণ্ঠপণ্য তৈরির আগে ডেভেলপার স্থানীয় পেজে মাইক্রোফোন থেকে কথিত উত্তর পর্যন্ত পুরো পথ পরীক্ষা করতে পারেন। Project মালিক key নিয়ন্ত্রণ করেন এবং API খরচ দেন।
- **যা খেয়াল রাখতে হবে:** স্থানীয় বিনিময় চললেই production প্রস্তুতি প্রমাণ হয় না। শেয়ার করা ব্যবস্থায় caller authentication ও খরচ নিয়ন্ত্রণ চাই; বাতিল বা timeout request ইতিমধ্যে OpenAI পৌঁছে যেতে পারে।
## শুরুর আগে
Node.js 22.6 বা পরের version এবং কাজ করে এমন মাইক্রোফোন ও speaker-সহ বর্তমান ব্রাউজার নিন। মাইক্রোফোনে প্রবেশে নিরাপদ context চাই; `http://localhost` এই স্থানীয় উদাহরণে উপযুক্ত। `gpt-realtime-2.1` access এবং billing চালু করা OpenAI API project key নিন। আগে rate ও spend limits দেখুন। মডেল পেজ Free tier অসমর্থিত বলে। স্বাভাবিক secret manager বা স্থানীয় shell ব্যবস্থা দিয়ে key server process environment-এ রাখুন। এটি `index.html`-এ রাখবেন না, `.env` ফাইলে commit বা transcript-এ paste করবেন না। [OpenAI WebRTC নির্দেশিকা](https://developers.openai.com/api/docs/guides/voice-webrtc) বিশ্বস্ত সার্ভারের বিনিময় নথিভুক্ত করে; [মডেল পেজ](https://developers.openai.com/api/docs/models/gpt-realtime-2.1) বর্তমান প্রবেশাধিকার ও দাম জানায়।
এটি Realtime API-র unified `/v1/realtime/calls` route। WebRTC নির্দেশিকায় `/v1/live/sessions` দিয়ে GPT-Live-ও আছে, তবে session protocol আলাদা। নিচের route ও payload একসঙ্গে রাখুন। উদাহরণ নিজের কম্পিউটারে বাঁধা; স্থানীয় Host ও Origin পরীক্ষা শেয়ার করা সেবার ব্যবহারকারীর authentication করে না।
1. ডেমোর জন্য ফাঁকা directory তৈরি করে সেখান থেকে Express install করুন:
```bash
npm init -y
npm install express
```
Installation `package.json` তৈরি করে ও web-server dependency যোগ করে। পরের দুই ফাইল একই directory-তে রাখুন। কোড Node-এর নিজস্ব `fetch`, `FormData` ও `AbortSignal.timeout` ব্যবহার করে; পরীক্ষিত ব্যবস্থায় Node.js 22.6 বা পরের version চাই।
2. নিচেরটি `server.mjs` নামে রাখুন। এটি ব্রাউজারের SDP offer (প্রস্তাবিত WebRTC connection-এর বর্ণনা) গ্রহণ করে Realtime session settings-সহ OpenAI পাঠায়। সাধারণ API key শুধু সার্ভারেই পড়া হয়।
```javascript
import express from "express";
const app = express();
// This demo accepts only the local page, including protection against DNS rebinding.
app.use((req, res, next) => {
const hosts = ["localhost:3000", "127.0.0.1:3000"];
if (!hosts.includes(req.get("host"))) return res.status(403).send("Local host required");
if (req.method === "POST" && req.get("origin") !== `http://${req.get("host")}`) {
return res.status(403).send("Same-origin local page required");
}
next();
});
app.use(express.text({ type: "application/sdp", limit: "64kb" }));
app.get("/", (_req, res) => res.sendFile("index.html", { root: process.cwd() }));
app.post("/session", async (req, res) => {
if (!process.env.OPENAI_API_KEY) return res.status(500).send("Server API key missing");
if (typeof req.body !== "string" || !req.body.startsWith("v=")) {
return res.status(400).send("Expected an SDP offer");
}
const form = new FormData();
form.set("sdp", req.body);
form.set("session", JSON.stringify({
type: "realtime",
model: "gpt-realtime-2.1",
output_modalities: ["audio"],
audio: { output: { voice: "marin" } },
instructions: "Be a concise, helpful voice assistant. Do not claim access to external tools."
}));
try {
const upstream = await fetch("https://api.openai.com/v1/realtime/calls", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.OPENAI_API_KEY}` },
body: form,
signal: AbortSignal.timeout(25000)
});
const answer = await upstream.text();
if (!upstream.ok) {
console.error("Realtime session rejected", upstream.status);
return res.status(502).send(`OpenAI session request failed (${upstream.status})`);
}
res.type("application/sdp").send(answer);
} catch (error) {
console.error("Realtime session network failure", error.name);
res.status(502).send("Could not reach the Realtime API");
}
});
app.listen(3000, "127.0.0.1", () => console.log("Open http://localhost:3000"));
```
সার্ভার `127.0.0.1:3000`-এ bind হয়ে শুধু স্থানীয় পেজের host ও POST origin গ্রহণ করে এবং SDP answer ফেরায়। 25 সেকেন্ড upstream deadline এই উদাহরণের সিদ্ধান্ত। Timeout বা ব্রাউজার বিচ্ছিন্ন হওয়া মানে OpenAI request নেয়নি নয়; অনিশ্চিত সূচনা পুনরাবৃত্তির আগে ব্যবহার দেখুন।
3. নিচেরটি `index.html` নামে রাখুন। পেজ **Start voice**-এর পরে মাইক্রোফোন অনুমতি চায়, স্থানীয় সার্ভারে offer পাঠায় এবং আসা audio বাজায়। **Stop** connection বন্ধ ও microphone tracks থামায়, setup চললেও। 30 সেকেন্ড setup timer-ও উদাহরণের সিদ্ধান্ত, API guarantee নয়।
```html
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>Local Realtime voice check</title>
<button id="start">Start voice</button>
<button id="stop" disabled>Stop</button>
<p id="status" role="status">Idle</p>
<audio id="reply" autoplay controls></audio>
<script type="module">
const start = document.querySelector("#start");
const stop = document.querySelector("#stop");
const status = document.querySelector("#status");
const reply = document.querySelector("#reply");
let current;
function closeSession(session = current, message = "Stopped") {
if (!session) return;
session.closed = true;
clearTimeout(session.timer);
session.abort.abort();
session.mic?.getTracks().forEach(track => track.stop());
if (session.pc) session.pc.onconnectionstatechange = null;
session.dc?.close();
session.pc?.close();
if (current === session) {
current = null;
reply.srcObject = null;
start.disabled = false;
stop.disabled = true;
status.textContent = message;
}
}
start.onclick = async () => {
const session = { abort: new AbortController(), closed: false };
current = session;
start.disabled = true;
stop.disabled = false;
status.textContent = "Requesting microphone";
session.timer = setTimeout(() => closeSession(session, "Setup timed out; microphone stopped"), 30000);
try {
const mic = await navigator.mediaDevices.getUserMedia({ audio: true });
if (session.closed) { mic.getTracks().forEach(track => track.stop()); return; }
session.mic = mic;
const pc = session.pc = new RTCPeerConnection();
pc.ontrack = event => { if (!session.closed) reply.srcObject = event.streams[0]; };
pc.onconnectionstatechange = () => {
if (session.closed) return;
status.textContent = `Connection: ${pc.connectionState}`;
if (pc.connectionState === "connected") clearTimeout(session.timer);
if (["failed", "closed", "disconnected"].includes(pc.connectionState)) {
closeSession(session, "Connection ended; microphone stopped. Start a new session.");
}
};
pc.addTrack(mic.getAudioTracks()[0], mic);
const dc = session.dc = pc.createDataChannel("oai-events");
dc.onmessage = message => {
if (session.closed) return;
try {
const event = JSON.parse(message.data);
if (event.type === "session.created") status.textContent = "Session ready: speak when connected";
if (event.type === "response.done") {
status.textContent = `Response status: ${event.response?.status || "unknown"}; verify audible playback`;
}
if (event.type === "error") closeSession(session, `Realtime error: ${event.error?.message || "unknown"}; stopped`);
} catch { closeSession(session, "Invalid event; stopped"); }
};
dc.onclose = () => { if (!session.closed) closeSession(session, "Event channel closed; stopped"); };
dc.onerror = () => closeSession(session, "Event channel failed; stopped");
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
if (session.closed) return;
// The official WebRTC example submits the generated offer directly.
const response = await fetch("/session", {
method: "POST",
headers: { "Content-Type": "application/sdp" },
body: offer.sdp,
signal: session.abort.signal
});
if (!response.ok) throw new Error(await response.text());
const answer = await response.text();
if (session.closed) return;
await pc.setRemoteDescription({ type: "answer", sdp: answer });
if (!session.closed && pc.connectionState !== "connected") status.textContent = "Signaling complete; waiting for connection";
} catch (error) {
if (!session.closed) closeSession(session, `Start failed: ${error.message}`);
}
};
stop.onclick = () => closeSession();
window.addEventListener("pagehide", () => closeSession());
</script>
</html>
```
Peer বা event-channel ব্যর্থতা এবং পেজ ছাড়লেও ব্রাউজার session বন্ধ করে। Stop বা timeout-এর পরে অনুমতি আসতে পারে; দেরির track বন্ধ হয়। Status line `response.done` ও তার ঘোষিত অবস্থা দেখায়। শুধু এই event উত্তর শোনা গেছে বা বাতিল/ব্যর্থ response সফল হয়েছে প্রমাণ করে না।
4. দুই ফাইলের directory থেকে সার্ভার চালান; তার process environment-এ `OPENAI_API_KEY` আগে থেকে set থাকতে হবে:
```bash
node server.mjs
```
খুলুন: `http://localhost:3000`. আপনার **Start voice**, **Stop**, **Idle** অবস্থা ও audio player দেখা উচিত। **Start voice** ক্লিক করে মাইক্রোফোন অনুমতি দিন এবং ছোট, অসংবেদনশীল প্রশ্ন বলুন। OpenAI-এর [Realtime conversations নির্দেশিকা](https://developers.openai.com/api/docs/guides/realtime-conversations) বলে default voice activity detection কথার পর বিরতিকে উত্তর শুরু করতে ব্যবহার করতে পারে। নিজের run সফল কিনা দেখুন: মাইক্রোফোন সক্রিয়, connection `connected` অবস্থায়, `session.created` event এসেছে, কথা শোনা যাচ্ছে এবং `response.done` completed response বলছে। **Stop** ক্লিক করে microphone indicator নিভেছে নিশ্চিত করুন। এই পরীক্ষা আপনার করার; BIG CHANGE অর্থপ্রদত্ত browser session চালায়নি।
## যাচাই ব্যর্থ হলে
মাইক্রোফোন অনুমতি না পেলে বা device না দেখলে browser permission ও device দেখুন, তারপর স্থানীয় `localhost` URL বা HTTPS নিন। পেজ `/session` failure দেখালে server HTTP status, key, project model access, billing, rate limits ও endpoint দেখুন। সার্ভার ইচ্ছাকৃতভাবে key বা OpenAI response body ছাপে না। 502 নেটওয়ার্ক ব্যর্থতা বা 25 সেকেন্ড deadline-ও বোঝাতে পারে; অনিশ্চিত upstream request গৃহীত হয়েছে কি না জানায় না।
Signaling সফল কিন্তু connection ব্যর্থ হলে page status, network restriction ও ফেরত SDP answer দেখুন। সংযোগ সচল কিন্তু নীরব হলে mic input ও বাছাই output দেখুন। Autoplay বন্ধ থাকতে পারে: audio control-এ **Play** ক্লিক করে প্রয়োজনে থামিয়ে নতুন session শুরু করুন। প্রতি ব্যর্থতায় **Stop** ব্যবহার করে microphone indicator নিভেছে নিশ্চিত করুন। Request ফল অনিশ্চিত হলে বারবার শুরুর আগে project usage দেখুন।
## খরচ, গোপনীয়তা ও সীমা
OpenAI অনুযায়ী `gpt-realtime-2.1`-এর noncached text input/output দাম **প্রতি দশ লক্ষ tokens $4/$24** এবং audio input/output **প্রতি দশ লক্ষ tokens $32/$64**; 19 অক্টোবর 2026 যাচাই। খরচ ব্যবহৃত tokens অনুযায়ী, পরের turns-এ আগের conversation context-সহ। ব্যবহারের আগে [মডেলের মূল্য ও সীমা](https://developers.openai.com/api/docs/models/gpt-realtime-2.1) এবং নিজের project usage দেখুন; শুধু সময় দিয়ে session bill অনুমান করা যায় না। [Realtime conversations নির্দেশিকা](https://developers.openai.com/api/docs/guides/realtime-conversations) সর্বোচ্চ session 60 মিনিট বলে।
Session চলাকালে মাইক্রোফোনের audio OpenAI যায়। পাঠানোর অধিকার আছে এমন কথা বলুন; ব্যক্তিগত বা তৃতীয় পক্ষের audio এড়ান। স্থানীয় পেজে sign-in বা প্রতি ব্যবহারকারীর budget control নেই। শেয়ার করা সেবায় authenticated, rate-limited `/session` access ও server-derived safety identifier চাই; স্থানীয় Host ও Origin পরীক্ষা যথেষ্ট নয়। উদাহরণ বাইরের tools বা phone call করে না। Latency, নির্ভরযোগ্যতা, কথার মান, সাশ্রয় বা production deployment ফল মাপা হয়নি।
## উৎস ও আরও পড়ুন
- [OpenAI WebRTC নির্দেশিকা](https://developers.openai.com/api/docs/guides/voice-webrtc): unified Realtime server exchange, browser audio path ও আলাদা GPT-Live protocol।
- [OpenAI Realtime conversations নির্দেশিকা](https://developers.openai.com/api/docs/guides/realtime-conversations): session events, turn behavior, response status ও সময়সীমা।
- [OpenAI `gpt-realtime-2.1` মডেল পেজ](https://developers.openai.com/api/docs/models/gpt-realtime-2.1): model access, token মূল্য ও rate limits। উদাহরণ চালানোর সময় মূল্য ও প্রবেশাধিকার আবার দেখুন।
## Sources
- [OpenAI WebRTC নির্দেশিকা](https://developers.openai.com/api/docs/guides/voice-webrtc) — Realtime unified calls interface, trusted key, SDP, browser audio ও আলাদা GPT-Live protocol।
- [OpenAI Realtime কথোপকথন](https://developers.openai.com/api/docs/guides/realtime-conversations) — Session events, VAD, response status ও 60 মিনিট সময়।
- [OpenAI gpt-realtime-2.1 মডেল](https://developers.openai.com/api/docs/models/gpt-realtime-2.1) — মডেলভিত্তিক token মূল্য ও প্রবেশাধিকার।
- [OpenAI কণ্ঠের খরচ অনুকূল করা](https://developers.openai.com/api/docs/guides/voice-latency-cost) — Context ও প্রতি response ব্যবহার।
- [OpenAI API ও ChatGPT billing](https://help.openai.com/en/articles/9039756-managing-billing-for-chatgpt-and-the-api-platform) — আলাদা billing ব্যবস্থা।
BIG CHANGE নিউজলেটার
বড় ছবিটা। আপনার গতিতে।
এআই ও রোবোটিক্স নিয়ে সাম্প্রতিক খবর, নজর রাখার মতো পরিবর্তন এবং কাজে লাগানোর ব্যবহারিক ধারণা। দৈনিক ব্রিফিং, সাপ্তাহিক সংকলন বা মাসিক দৃষ্টিভঙ্গি বেছে নিন।
Next scheduled send (UTC): . Your first edition arrives at the next scheduled send after you confirm.
আপনার গোপনীয়তা, আপনার পছন্দ।
প্রয়োজনীয় স্টোরেজ সাইটের নিরাপত্তায় সাহায্য করে এবং আপনার পছন্দ মনে রাখে। আপনি অনুমতি না দেওয়া পর্যন্ত ঐচ্ছিক Google Analytics বন্ধ থাকবে। প্রয়োজনীয় স্টোরেজ ব্যবহার করেই প্রতিটি গল্প পড়তে পারেন। গোপনীয়তার বিবরণ