Wixzel Voice के साथ Flutter ऐप में अपने एजेंट का मैस्कट दिखाएँ
इस गाइड के अंत तक आपका Flutter ऐप आपके एजेंट का मैस्कट दिखाएगा, वह एनिमेटेड चेहरा जो हर Wixzel Voice एजेंट के पास होता है, और वह लाइव कॉल के साथ सुनता, सोचता और बोलता है। wixzel_voice_flutter पैकेज उसे AgentMascotView से बनाता है और MascotRealtimeLink से कॉल के साथ तालमेल में रखता है; कॉल wixzel_voice Dart SDK संभालता है। लगभग एक घंटा लगेगा, ज़्यादातर रिकॉर्डर और प्लेयर जोड़ने में। एक सेशन उसी इंजन पर फ़ोन कॉल की तरह बिल होता है: Gemini Live पर $0.0491 प्रति कनेक्टेड मिनट, चार मिनट के लिए लगभग $0.20, बिना फ़ोन लाइन के।
लेखक Aqeel Shamsudheen · प्रकाशित · अपडेट
- समय
- लगभग एक घंटा
- इंजन
- gemini-live
- इंजन टाइम
- $0.0491 प्रति कनेक्टेड मिनट

शुरू करने से पहले आपको क्या चाहिए?
- एक Wixzel Voice एजेंट और क्रेडिट वाली API की, जो आपके सर्वर पर रहे। कोई भी एजेंट चलेगा: हर एजेंट के पास मैस्कट होता है, शुरुआत में डिफ़ॉल्ट हरे रंग वाला।
- Flutter 3.27 या नया।
- आपके कंट्रोल वाला एक सर्वर जो API कॉल कर सके। उदाहरण में Node.js और TypeScript SDK है।
- एक रिकॉर्डिंग प्लगइन जो 16-bit PCM स्ट्रीम करे, बेहतर हो कि 8 kHz मोनो पर echo cancellation के साथ, और एक प्लेयर जो raw PCM ले, जैसे
recordऔरflutter_pcm_sound।
इसे Wixzel Voice पर स्टेप-बाय-स्टेप कैसे बनाएँ?
01पैकेज जोड़ें
wixzel_voice_flutterमैस्कट बनाता है;wixzel_voiceवह Dart SDK है जिस पर यह बना है:pubspec.yamldependencies: wixzel_voice: ^0.8.0 wixzel_voice_flutter: ^0.1.0 http: ^1.2.0यह पैकेज
sensors_plusपर निर्भर है, ताकि मैस्कट की आँखें फ़ोन के झुकाव के साथ घूम सकें, औरvisibility_detectorपर, ताकि वह सिर्फ़ स्क्रीन पर दिखते समय ही एनिमेट हो। यह ऑडियो रिकॉर्ड या प्ले नहीं करता।02ऐप को एजेंट और सेशन अपने सर्वर से दें
आपकी API की कभी ऐप में नहीं जाती। आपका सर्वर एजेंट लाता है और एक मिनट का, एक बार इस्तेमाल होने वाला सेशन बनाता है, और ऐप दोनों आपके सर्वर से माँगता है:
server.mjsimport express from 'express'; import { WixzelVoice } from 'wixzel-voice'; const wixzel = new WixzelVoice({ apiKey: process.env.WIXZEL_API_KEY }); const app = express(); const AGENT_ID = process.env.AGENT_ID; // Put your own sign-in check in front of both routes. app.get('/agent', async (req, res) => { res.json(await wixzel.agents.retrieve(AGENT_ID)); }); app.post('/session', async (req, res) => { res.json(await wixzel.realtime.createSession({ agent_id: AGENT_ID, max_duration_seconds: 300 })); }); app.listen(3000);एजेंट के JSON में
mascot.specहोता है, वह छोटा spec जिससे मैस्कट बनता है। सेशन बनाने का कोई खर्च नहीं; बिलिंग तब शुरू होती है जब ऐप कनेक्ट होता है।03मैस्कट दिखाएँ
Agent.fromJsonआपके सर्वर का भेजा डेटा पढ़ता है, औरAgentMascotViewउसे दिखाता है:agent_face.dartimport 'dart:convert'; import 'package:flutter/widgets.dart'; import 'package:http/http.dart' as http; import 'package:wixzel_voice/wixzel_voice.dart'; import 'package:wixzel_voice_flutter/wixzel_voice_flutter.dart'; const backendUrl = 'https://api.example.com'; Future<Agent> loadAgent() async { final res = await http.get(Uri.parse('$backendUrl/agent')); return Agent.fromJson(jsonDecode(res.body) as Map<String, dynamic>); } Widget agentFace(Agent agent, MascotController controller) => AgentMascotView(agent: agent, controller: controller, size: 220); // In a list, draw one frame and run no animation: Widget agentRow(Agent agent) => AgentMascotView(agent: agent, size: 40, still: true);जिस एजेंट का कोई spec नहीं है, उसे डिफ़ॉल्ट रूप मिलता है। लगभग काला या लगभग सफ़ेद मैस्कट अपने ही रंग के एक स्टेज पर दिखता है, ताकि वह गहरी या हल्की स्क्रीन में गायब न हो जाए; इसे
stage: falseसे बंद करें। टैप करने पर एक expression चलता है, औरMascotControllerनाम से मूव चलाता है, जैसेmascot.play('hello')।04मैस्कट को कॉल से जोड़ें
Dart SDK के
RealtimeConnectionसे कनेक्ट करें और उसेMascotRealtimeLinkको दें। लिंक कॉल कनेक्ट होते समय मैस्कट को सोचता हुआ दिखाता है, hello में हाथ हिलवाता है, यूज़र के बोलते समय सुनता हुआ दिखाता है, और एजेंट के ऑडियो के साथ उसका मुँह हिलाता है:talk.dartimport 'dart:async'; import 'dart:convert'; import 'dart:typed_data'; import 'package:http/http.dart' as http; import 'package:wixzel_voice/wixzel_voice.dart'; import 'package:wixzel_voice_flutter/wixzel_voice_flutter.dart'; /// Your audio plugins, behind a small interface. abstract class PcmPlayer { void add(Int16List samples); // 16-bit PCM, 8 kHz mono void clear(); } class MascotCall { MascotCall(this.mascot, this.player); final MascotController mascot; final PcmPlayer player; RealtimeConnection? _conn; MascotRealtimeLink? _link; StreamSubscription<Int16List>? _mic; /// [micFrames] is 16-bit PCM at 8 kHz in 160-sample (20 ms) frames. Future<void> start(Stream<Int16List> micFrames) async { final res = await http.post(Uri.parse('https://api.example.com/session')); final session = RealtimeSession.fromJson(jsonDecode(res.body) as Map<String, dynamic>); final conn = RealtimeConnection.forSession(session); _conn = conn; _link = MascotRealtimeLink(mascot, conn); conn.events.listen((event) { switch (event) { case RealtimeAudio(:final mulaw): player.add(mulawToPcm16(mulaw)); // the mouth follows this audio through the link case RealtimeAudioClear(): player.clear(); // the user spoke over the agent case RealtimeEnded(): unawaited(end()); default: } }); await conn.ready; _mic = micFrames.listen((frame) { conn.sendAudio(pcm16ToMulaw(frame)); _link?.micAudio(frame); // it leans in while the user talks }); } Future<void> end() async { await _mic?.cancel(); await _link?.dispose(); // leaves the mascot idle; does not end the call await _conn?.end(); _mic = null; _link = null; _conn = null; } }इसे
AgentMascotView(agent: agent, controller: mascot)से दिखाएँ, उसी controller के साथ जिसे कॉल चलाती है। स्क्रीन हटने पर controller को dispose करें।अपने रिकॉर्डर में प्लेटफ़ॉर्म का echo cancellation चालू करें, नहीं तो एजेंट स्पीकर से अपनी ही आवाज़ सुनता है और खुद को बीच में टोक देता है।
05अगर आपका प्लेयर ऑडियो शेड्यूल करता है, तो lip-sync बिल्कुल सटीक करें
डिफ़ॉल्ट रूप से लिंक मानता है कि आपका प्लेयर हर chunk आने के लगभग 120 ms बाद उसे चलाना शुरू करता है। अगर आपके प्लेयर को ठीक-ठीक पता है कि कोई chunk कब चलेगा, तो लिंक को वही बताएँ:
exact_timing.dartimport 'dart:typed_data'; import 'package:wixzel_voice/wixzel_voice.dart'; import 'package:wixzel_voice_flutter/wixzel_voice_flutter.dart'; MascotRealtimeLink exactLink(MascotController mascot, RealtimeConnection conn) => MascotRealtimeLink(mascot, conn, estimatePlayback: false); // In your player, each time it schedules a chunk, on the player's own clock: void scheduled(MascotRealtimeLink link, Int16List pcm, double playAt, double now) { link.agentAudio(pcm, playAt: playAt, currentTime: now, sampleRate: 8000); }
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 |
पैकेज मुफ़्त हैं और MIT लाइसेंस वाले हैं। मैस्कट दिखाने का कोई खर्च नहीं; क्रेडिट सिर्फ़ लाइव सेशन में खर्च होता है, इंजन की प्रति मिनट कीमत पर, प्रति सेकंड, आपके प्रीपेड बैलेंस से।
प्रीपेड, बिना सब्सक्रिप्शन और बिना फ़्री टियर: $5 से क्रेडिट जोड़ें और इस्तेमाल उसी से कटता है। अपने इस्तेमाल का अनुमान लगाएँ।
इस बिल्ड पर Wixzel Voice की कौन-सी सीमाएँ लागू होती हैं?
- पैकेज ऑडियो रिकॉर्ड या प्ले नहीं करता। दोनों आपका ऐप अपनी पसंद के प्लगइन से देता है।
- फ़ोन जैसा ऑडियो: दोनों दिशाओं में 8 kHz पर G.711 µ-law।
- सेशन अकाउंट की एक साथ चलने वाली कॉल की सीमा में गिने जाते हैं, जो डिफ़ॉल्ट रूप से पाँच है।
- Flutter 3.27 या नया। झुकाव के लिए accelerometer चाहिए; उसके बिना मैस्कट खुद ही इधर-उधर देखता है।
- मैस्कट का रूप बदलना आपके सर्वर से होने वाली API कॉल है (
agents.updateMascot), ऐप से नहीं, क्योंकि इसके लिए आपकी API की चाहिए।
अक्सर पूछे जाने वाले सवाल
Flutter में Wixzel Voice एजेंट का मैस्कट कैसे दिखाएँ?
wixzel_voice और wixzel_voice_flutter जोड़ें, आपके सर्वर से लाया गया एजेंट Agent.fromJson से पढ़ें, और उसे AgentMascotView(agent: agent) से दिखाएँ। कोड से चलाने के लिए एक MascotController दें।मैस्कट एजेंट के साथ lip-sync कैसे करता है?
MascotRealtimeLink RealtimeConnection के events सुनता है और एजेंट के ऑडियो के साथ मुँह हिलाता है; टाइमिंग आपके प्लेयर की देरी के उसके अपने अनुमान से तय होती है, या estimatePlayback: false के साथ, उन समयों से जो आपका प्लेयर agentAudio के ज़रिए बताता है। यह स्टेट भी सेट करता है: कनेक्ट होते समय सोचना, यूज़र के बोलते समय सुनना, कॉल खत्म होने पर idle।क्या मैस्कट वेबसाइट जैसा ही दिखता है?
क्या वेब ऐप के लिए भी ऐसा ही कुछ है?
wixzel-voice/mascot का mountMascot (npm पर wixzel-voice 0.10.0) मैस्कट को canvas पर बनाता है, और face.connect(session) मैस्कट से जुड़ी realtime कॉल शुरू करता है, माइक्रोफ़ोन और प्लेबैक समेत।और कहाँ पढ़ें
- SDKडॉक्स
Dart और TypeScript SDK और मैस्कट विजेट।
- मैस्कटडॉक्स
spec, रूप बदलना, और वेबसाइट से नया रूप बनाना।
- Realtime: वेब और मोबाइलडॉक्स
सेशन बनाना, प्रोटोकॉल और बिलिंग।
Wixzel Voice के बारे में
Wixzel Voice एक वॉइस AI API है, जिससे ऐसे AI एजेंट बनते हैं जो आपके अपने SIP ट्रंक पर असली फ़ोन कॉल करते और उनका जवाब देते हैं, या आपके वेब और मोबाइल ऐप में लोगों से बात करते हैं। एक API की और एक प्रीपेड बैलेंस हर वॉइस इंजन को कवर करते हैं, और बिल असली इस्तेमाल के हर सेकंड के हिसाब से बनता है।
और गाइड
Claude Code या claude.ai में Claude आपके SIP ट्रंक से असली कॉल करता है और ट्रांसक्रिप्ट पढ़कर बताता है, और कुछ भी डायल होने से पहले आपसे पुष्टि लेता है।
आपके मौजूदा Twilio नंबर पर एक AI रिसेप्शनिस्ट जवाब देता है और API में अपॉइंटमेंट बुक करता है, Node.js में बना हुआ।
दो फ़ोन एजेंट, एक हिंदी और एक मलयालम बोलने वाला, Sarvam के भारतीय भाषा मॉडल पर, जो आपके SIP ट्रंक से कॉल का जवाब देते हैं या कॉल करते हैं।
एक Flutter ऐप जिसमें यूज़र WebSocket पर आपके वॉइस एजेंट से बात करते हैं, API की आपके सर्वर पर रहती है और कोई फ़ोन नंबर शामिल नहीं होता।
चार cURL रिक्वेस्ट से आपके SIP ट्रंक पर असली फ़ोन को कॉल करता Gemini Live एजेंट, और ट्रांसक्रिप्ट और खर्च के साथ कॉल रिकॉर्ड।
लीड की एक लिस्ट, जिसे आपका एजेंट आपके SIP ट्रंक पर, एक साथ चलने वाली कॉल की आपकी सीमा के हिसाब से बैच में कॉल करता है, और हर कॉल का स्टेटस और ट्रांसक्रिप्ट वापस पढ़ा जाता है।
आपकी वेबसाइट के कोने में एक बोलने वाला मैस्कट, जिसे विज़िटर ब्राउज़र से कॉल करते हैं, आपके डोमेन और आपकी रोज़ की सीमाओं तक सीमित, और हर कॉलर की लिस्ट के साथ।
अपना पहला वॉइस एजेंट बनाएँ

