Wixzel Voice के साथ WebSocket पर Flutter वॉइस एजेंट जोड़ें
इस गाइड के अंत तक आपके Flutter ऐप में यूज़र आपके बनाए वॉइस एजेंट से WebSocket पर बात कर सकेंगे, बिना SIP ट्रंक और बिना फ़ोन नंबर के। आपका सर्वर एक बार इस्तेमाल होने वाला सेशन बनाता है, इसलिए आपकी API की कभी ऐप तक नहीं पहुँचती, और wixzel_voice Dart SDK प्रोटोकॉल संभालता है। लगभग एक घंटा लगेगा, ज़्यादातर माइक्रोफ़ोन और स्पीकर जोड़ने में। एक सेशन उसी इंजन पर फ़ोन कॉल की तरह बिल होता है: Gemini Live इंजन पर $0.0491 प्रति कनेक्टेड मिनट, चार मिनट के सेशन के लिए लगभग $0.20, प्रीपेड बैलेंस से प्रति सेकंड, और टेलीफ़ोनी का कोई खर्च नहीं।
लेखक Aqeel Shamsudheen · प्रकाशित · अपडेट
- समय
- लगभग एक घंटा
- इंजन
- gemini-live
- इंजन टाइम
- $0.0491 प्रति कनेक्टेड मिनट
शुरू करने से पहले आपको क्या चाहिए?
- क्रेडिट वाली Wixzel Voice API की, जो आपके सर्वर पर रहे।
- सेशन बनाने के लिए आपके कंट्रोल वाला एक सर्वर। उदाहरण में Node.js और Express है; कोई भी भाषा जो HTTPS रिक्वेस्ट भेज सके, काम करेगी।
- एक Flutter ऐप, जिसमें 16-bit PCM स्ट्रीम करने वाला रिकॉर्डिंग प्लगइन हो, बेहतर हो कि 8 kHz मोनो पर echo cancellation के साथ, और एक प्लेयर जो raw PCM लेता हो।
इसे Wixzel Voice पर स्टेप-बाय-स्टेप कैसे बनाएँ?
01एजेंट एक बार बनाएँ
यह एजेंट Gemini Live इस्तेमाल करता है, एक realtime मॉडल जो सुनता है, सोचता है और बोलता है:
shellcurl https://api.voice.wixzel.com/v1/agents \ -H "Authorization: Bearer $WIXZEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "In-app assistant", "system_prompt": "You are the voice assistant inside the Acme app. Answer in one or two short sentences.", "opening_message": "Hi, what can I help you with?", "voice": { "realtime": { "model": "google/gemini-live", "voice": "Kore" } } }'इस एजेंट में कुछ भी ऐप के लिए खास नहीं है: यही एजेंट किसी फ़ोन नंबर पर भी जवाब दे सकता है। इसका
idअपने सर्वर परAGENT_IDके रूप में रखें।02अपने सर्वर पर सेशन बनाएँ
ऐप के पास कभी आपकी API की नहीं होती। वह आपके सर्वर से पूछता है, और आपका सर्वर
POST /v1/realtime/sessionsसे API से सेशन माँगता है, यहाँ TypeScript SDK के ज़रिए:server.mjsimport express from 'express'; import { WixzelVoice } from 'wixzel-voice'; const wixzel = new WixzelVoice({ apiKey: process.env.WIXZEL_API_KEY }); const app = express(); // Replace with your own authentication. It must set req.userId. function requireUser(req, res, next) { req.userId = 'demo-user'; next(); } app.post('/voice/session', requireUser, async (req, res) => { const session = await wixzel.realtime.createSession({ agent_id: process.env.AGENT_ID, max_duration_seconds: 300, metadata: { user_id: req.userId }, }); res.json(session); }); app.listen(3000);रिस्पॉन्स में सॉकेट का
url, एकclient_secretजो सिर्फ़ एक बार, एक मिनट के लिए, इसी एजेंट के लिए काम करता है, औरaudio_format: "mulaw_8000"होता है। सेशन बनाने का कोई खर्च नहीं; बिलिंग तब शुरू होती है जब ऐप कनेक्ट होता है।max_duration_secondsबातचीत की अधिकतम अवधि तय करता है, 10 से 3600 सेकंड तक, डिफ़ॉल्ट 600।metadataकॉल रिकॉर्ड पर वापस दिखता है और मॉडल को कभी नहीं भेजा जाता।allowed_originsसिर्फ़ ब्राउज़र के लिए मायने रखता है, इसलिए नेटिव ऐप इसे छोड़ देता है।03ऐप से कनेक्ट करें
flutter pub add wixzel_voice httpसे SDK जोड़ें, फिर आपके सर्वर से मिला सेशन खोलें:voice_call.dartimport 'dart:async'; import 'dart:convert'; import 'dart:typed_data'; import 'package:http/http.dart' as http; import 'package:wixzel_voice/wixzel_voice.dart'; /// Whatever your playback plugin offers, behind a small interface. abstract class PcmPlayer { void add(Int16List samples); void clear(); } class VoiceCall { VoiceCall({required this.player, required this.onLine}); final PcmPlayer player; final void Function(String role, String text) onLine; RealtimeConnection? _conn; StreamSubscription<Uint8List>? _mic; final List<int> _pending = []; /// [micBytes] is 16-bit little-endian PCM, 8 kHz mono, from your recording plugin. Future<void> start(Stream<Uint8List> micBytes) async { final res = await http.post(Uri.parse('https://api.example.com/voice/session')); final status = res.statusCode; if (status != 200) throw Exception('Could not start a voice session: HTTP $status'); final session = RealtimeSession.fromJson(jsonDecode(res.body) as Map<String, dynamic>); final conn = RealtimeConnection.forSession(session); _conn = conn; conn.events.listen((event) { switch (event) { case RealtimeAudio(:final mulaw): player.add(mulawToPcm16(mulaw)); case RealtimeAudioClear(): player.clear(); // the user interrupted: drop queued audio case RealtimeTranscript(:final role, :final text): onLine(role, text); case RealtimeError(:final code, :final message): onLine('error', '$code: $message'); case RealtimeEnded(:final reason): onLine('system', 'ended: $reason'); _mic?.cancel(); default: } }); await conn.ready; _mic = micBytes.listen(_send); } void _send(Uint8List bytes) { final data = ByteData.sublistView(bytes); for (var i = 0; i + 1 < bytes.length; i += 2) { _pending.add(data.getInt16(i, Endian.little)); } // 160 samples is 20 ms at 8 kHz, the frame size the server expects. while (_pending.length >= 160) { final frame = Int16List.fromList(_pending.sublist(0, 160)); _pending.removeRange(0, 160); _conn?.sendAudio(pcm16ToMulaw(frame)); } } Future<void> end() async { await _mic?.cancel(); await _conn?.end(); } }RealtimeConnectionसिर्फ़ प्रोटोकॉल संभालता है: यह माइक्रोफ़ोन या स्पीकर नहीं खोलता, जिससे SDK प्लगइन dependencies से मुक्त रहता है और आप वही ऑडियो प्लगइन इस्तेमाल कर सकते हैं जो आपके पास पहले से हैं।pcm16ToMulawऔरmulawToPcm1616-bit PCM और wire पर जाने वाले फ़ॉर्मैट के बीच बदलते हैं।पहले माइक्रोफ़ोन की अनुमति माँगें: Android पर
RECORD_AUDIOऔर iOS परNSMicrophoneUsageDescription।04echo cancellation चालू करें, और फ़ोन जैसी ऑडियो क्वालिटी की उम्मीद रखें
रिकॉर्डिंग प्लगइन में अपने प्लेटफ़ॉर्म का echo cancellation चालू करें। इसके बिना एजेंट स्पीकर से अपनी ही आवाज़ सुनता है और खुद को बीच में टोक देता है।
ऑडियो दोनों दिशाओं में 8 kHz पर G.711 µ-law है, बिल्कुल फ़ोन लाइन जैसा, क्योंकि सेशन उसी मीडिया पाथ से चलते हैं जिससे कॉल। बोली के लिए यह ठीक है, पर wideband ऑडियो से कम। अगर आपका प्लगइन अनुमति दे तो 8 kHz पर रिकॉर्ड करें, नहीं तो
pcm16ToMulawसे पहले resample करें, और एजेंट का ऑडियो 8 kHz मोनो पर चलाएँ।05बाद में सेशन पढ़ें
हर सेशन
channel: "web"वाला एक कॉल रिकॉर्ड है:shellcurl "https://api.voice.wixzel.com/v1/calls?channel=web&limit=5" \ -H "Authorization: Bearer $WIXZEL_API_KEY"वेब सेशन इनकमिंग होता है, उसमें
fromयाtoनहीं होता, और उसमें अवधि,cost_microsऔर आपकाmetadataहोता है;GET /v1/calls/{id}ट्रांसक्रिप्ट भी देता है। यह उसीcallCompletedwebhook के साथ खत्म होता है जो फ़ोन कॉल भेजती है। वेब सेशन रिकॉर्ड नहीं होते।
Wixzel Voice पर इस बिल्ड की लागत कितनी है?
$0.0491 प्रति कनेक्टेड मिनट पर gemini-live इंजन पर 4 मिनट के सेशन का इंजन टाइम: हर सेशन पर लगभग $0.20। टेलीफ़ोनी की कोई लागत नहीं है, क्योंकि कोई फ़ोन लाइन नहीं है।
| हर महीने के सेशन | कनेक्टेड मिनट | हर महीने का इंजन खर्च |
|---|---|---|
| 500 | 2,000 | $98.20 |
| 2,500 | 10,000 | $491 |
| 10,000 | 40,000 | $1,964 |
एक सेशन का खर्च उसी इंजन पर फ़ोन कॉल जितना है, प्रति सेकंड, उसी प्रीपेड बैलेंस से। सेशन बनाने का कोई खर्च नहीं, इसलिए जो यूज़र स्क्रीन खोलकर माइक्रोफ़ोन की अनुमति नहीं देता, उसका भी कोई खर्च नहीं।
प्रीपेड, बिना सब्सक्रिप्शन और बिना फ़्री टियर: $5 से क्रेडिट जोड़ें और इस्तेमाल उसी से कटता है। अपने इस्तेमाल का अनुमान लगाएँ।
इस बिल्ड पर Wixzel Voice की कौन-सी सीमाएँ लागू होती हैं?
- फ़ोन जैसा ऑडियो: दोनों दिशाओं में 8 kHz पर G.711 µ-law, wideband नहीं।
- Dart SDK ऑडियो रिकॉर्ड या प्ले नहीं करता। माइक्रोफ़ोन और स्पीकर आपका ऐप अपनी पसंद के प्लगइन से देता है।
- सेशन फ़ोन कॉल के साथ अकाउंट की एक साथ चलने वाली कॉल की सीमा में गिने जाते हैं, जो डिफ़ॉल्ट रूप से पाँच है। माँगने पर यह सीमा बढ़ाई जाती है।
- एक सेशन डिफ़ॉल्ट रूप से 10 मिनट और ज़्यादा से ज़्यादा एक घंटा चलता है, और दो मिनट की खामोशी उसे खत्म कर देती है।
- वेब सेशन रिकॉर्ड नहीं होते, और यूज़र को किसी व्यक्ति तक ट्रांसफ़र करने के लिए दूसरी लाइन नहीं है।
अक्सर पूछे जाने वाले सवाल
क्या Flutter के लिए कोई वॉइस एजेंट API है?
wixzel_voice, में RealtimeConnection है, जो Flutter या Dart ऐप को WebSocket पर वॉइस एजेंट से जोड़ता है। सेशन आपका सर्वर आपकी API की से बनाता है; ऐप के पास सिर्फ़ एक मिनट का, एक बार इस्तेमाल होने वाला secret होता है।क्या ऐप के अंदर वॉइस एजेंट के लिए फ़ोन नंबर या SIP ट्रंक चाहिए?
एजेंट बार-बार खुद को बीच में क्यों टोकता है?
क्या ऐप में कोई दूसरा इंजन इस्तेमाल किया जा सकता है?
सेशन के बीच अकाउंट का क्रेडिट खत्म हो जाए तो क्या होता है?
low_balance के साथ एक session.warning मिलता है, जिसमें लगभग कितने सेकंड बचे हैं यह होता है, फिर सेशन insufficient_credits वजह के साथ खत्म हो जाता है। जिस सेशन के लिए बिल्कुल क्रेडिट न हो, वह close code 4402 के साथ रिजेक्ट हो जाता है।और कहाँ पढ़ें
- Realtime: वेब और मोबाइलडॉक्स
सेशन बनाना, प्रोटोकॉल, रिजेक्शन कोड और बिलिंग।
- SDKडॉक्स
Dart और TypeScript SDK, ब्राउज़र क्लाइंट समेत।
- वॉइस इंजनडॉक्स
Realtime और कंपोज़ की गई आवाज़ें, और आवाज़ों की लिस्ट।
- Webhookडॉक्स
वेब सेशन के लिए callCompleted, आपके metadata के साथ।
Wixzel Voice के बारे में
Wixzel Voice एक वॉइस AI API है, जिससे ऐसे AI एजेंट बनते हैं जो आपके अपने SIP ट्रंक पर असली फ़ोन कॉल करते और उनका जवाब देते हैं, या आपके वेब और मोबाइल ऐप में लोगों से बात करते हैं। एक API की और एक प्रीपेड बैलेंस हर वॉइस इंजन को कवर करते हैं, और बिल असली इस्तेमाल के हर सेकंड के हिसाब से बनता है।
और गाइड
Claude Code या claude.ai में Claude आपके SIP ट्रंक से असली कॉल करता है और ट्रांसक्रिप्ट पढ़कर बताता है, और कुछ भी डायल होने से पहले आपसे पुष्टि लेता है।
आपके मौजूदा Twilio नंबर पर एक AI रिसेप्शनिस्ट जवाब देता है और API में अपॉइंटमेंट बुक करता है, Node.js में बना हुआ।
दो फ़ोन एजेंट, एक हिंदी और एक मलयालम बोलने वाला, Sarvam के भारतीय भाषा मॉडल पर, जो आपके SIP ट्रंक से कॉल का जवाब देते हैं या कॉल करते हैं।
चार cURL रिक्वेस्ट से आपके SIP ट्रंक पर असली फ़ोन को कॉल करता Gemini Live एजेंट, और ट्रांसक्रिप्ट और खर्च के साथ कॉल रिकॉर्ड।
लीड की एक लिस्ट, जिसे आपका एजेंट आपके SIP ट्रंक पर, एक साथ चलने वाली कॉल की आपकी सीमा के हिसाब से बैच में कॉल करता है, और हर कॉल का स्टेटस और ट्रांसक्रिप्ट वापस पढ़ा जाता है।
आपकी वेबसाइट के कोने में एक बोलने वाला मैस्कट, जिसे विज़िटर ब्राउज़र से कॉल करते हैं, आपके डोमेन और आपकी रोज़ की सीमाओं तक सीमित, और हर कॉलर की लिस्ट के साथ।
एक Flutter स्क्रीन, जिसमें आपके एजेंट का मैस्कट realtime कॉल के दौरान एजेंट की आवाज़ के साथ मुँह हिलाता है, और आपकी API की आपके सर्वर पर रहती है।
अपना पहला वॉइस एजेंट बनाएँ

