Token导航 LogoToken导航TokenDH.com
待分类需要联网github未标认证来源可访问许可证需确认审计提醒

telnyx-webrtc-client-fluttertelnyx webrtc client Flutter 命令行

Agent Skill

telnyx-webrtc-client-flutter 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

643

周安装

26

GitHub Stars

169

下载量

202
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:telnyx-webrtc-client-flutter(telnyx webrtc client Flutter 命令行)
来源仓库:https://github.com/team-telnyx/skills
仓库路径:skills/telnyx-webrtc-client-flutter
安装命令:
npx skills add https://github.com/team-telnyx/skills --skill telnyx-webrtc-client-flutter
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/team-telnyx/skills --skill telnyx-webrtc-client-flutter

简介

用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息。

  • 适合在需要围绕仓库状态、代码变更或协作事项进行整理时使用。
  • 通过 GitHub 安装,支持 Codex、Claude、Cursor、Gemini CLI 等宿主环境。
  • 使用前应确认权限范围与维护状态,避免触发不必要的联网、命令执行或文件读写。
  • 建议结合原始 README 核验具体用法后再部署。

SKILL.md

Telnyx WebRTC - Flutter SDK

Build real-time voice communication into Flutter applications (Android, iOS, Web).

Prerequisites: Create WebRTC credentials and generate a login token using the Telnyx server-side SDK. See the telnyx-webrtc-* skill in your server language plugin (e.g., telnyx-python, telnyx-javascript).

Quick Start Option

For faster implementation, consider Telnyx Common - a higher-level abstraction that simplifies WebRTC integration with minimal setup.

Installation

Add to pubspec.yaml:

dependencies:
  telnyx_webrtc: ^latest_version

Then run:

flutter pub get

Platform Configuration

Android

Add to AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

iOS

Add to Info.plist:

<key>NSMicrophoneUsageDescription</key>
<string>$(PRODUCT_NAME) needs microphone access for calls</string>

Authentication

Option 1: Credential-Based Login

final telnyxClient = TelnyxClient();

final credentialConfig = CredentialConfig(
  sipUser: 'your_sip_username',
  sipPassword: 'your_sip_password',
  sipCallerIDName: 'Display Name',
  sipCallerIDNumber: '+15551234567',
  notificationToken: fcmOrApnsToken,  // Optional: for push
  autoReconnect: true,
  debug: true,
  logLevel: LogLevel.debug,
);

telnyxClient.connectWithCredential(credentialConfig);

Option 2: Token-Based Login (JWT)

final tokenConfig = TokenConfig(
  sipToken: 'your_jwt_token',
  sipCallerIDName: 'Display Name',
  sipCallerIDNumber: '+15551234567',
  notificationToken: fcmOrApnsToken,
  autoReconnect: true,
  debug: true,
);

telnyxClient.connectWithToken(tokenConfig);

Configuration Options

ParameterTypeDescription
sipUser / sipTokenStringCredentials from Telnyx Portal
sipCallerIDNameStringCaller ID name displayed to recipients
sipCallerIDNumberStringCaller ID number
notificationTokenString?FCM (Android) or APNS (iOS) token
autoReconnectboolAuto-retry login on failure
debugboolEnable call quality metrics
logLevelLogLevelnone, error, warning, debug, info, all
ringTonePathString?Custom ringtone asset path
ringbackPathString?Custom ringback tone asset path

Making Outbound Calls

telnyxClient.call.newInvite(
  'John Doe',           // callerName
  '+15551234567',       // callerNumber
  '+15559876543',       // destinationNumber
  'my-custom-state',    // clientState
);

Receiving Inbound Calls

Listen for socket events:

InviteParams? _incomingInvite;
Call? _currentCall;

telnyxClient.onSocketMessageReceived = (TelnyxMessage message) {
  switch (message.socketMethod) {
    case SocketMethod.CLIENT_READY:
      // Ready to make/receive calls
      break;

    case SocketMethod.LOGIN:
      // Successfully logged in
      break;

    case SocketMethod.INVITE:
      // Incoming call!
      _incomingInvite = message.message.inviteParams;
      // Show incoming call UI...
      break;

    case SocketMethod.ANSWER:
      // Call was answered
      break;

    case SocketMethod.BYE:
      // Call ended
      break;
  }
};

// Accept the incoming call
void acceptCall() {
  if (_incomingInvite != null) {
    _currentCall = telnyxClient.acceptCall(
      _incomingInvite!,
      'My Name',
      '+15551234567',
      'state',
    );
  }
}

Call Controls

// End call
telnyxClient.call.endCall(telnyxClient.call.callId);

// Decline incoming call
telnyxClient.createCall().endCall(_incomingInvite?.callID);

// Mute/Unmute
telnyxClient.call.onMuteUnmutePressed();

// Hold/Unhold
telnyxClient.call.onHoldUnholdPressed();

// Toggle speaker
telnyxClient.call.enableSpeakerPhone(true);

// Send DTMF tone
telnyxClient.call.dtmf(telnyxClient.call.callId, '1');

Push Notifications - Android (FCM)

1. Setup Firebase

// main.dart
@pragma('vm:entry-point')
Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  if (defaultTargetPlatform == TargetPlatform.android) {
    await Firebase.initializeApp();
    FirebaseMessaging.onBackgroundMessage(_firebaseBackgroundHandler);
  }

  runApp(const MyApp());
}

2. Background Handler

Future<void> _firebaseBackgroundHandler(RemoteMessage message) async {
  // Show notification (e.g., using flutter_callkit_incoming)
  showIncomingCallNotification(message);

  // Listen for user action
  FlutterCallkitIncoming.onEvent.listen((CallEvent? event) {
    switch (event!.event) {
      case Event.actionCallAccept:
        TelnyxClient.setPushMetaData(
          message.data,
          isAnswer: true,
          isDecline: false,
        );
        break;
      case Event.actionCallDecline:
        TelnyxClient.setPushMetaData(
          message.data,
          isAnswer: false,
          isDecline: true,  // SDK handles decline automatically
        );
        break;
    }
  });
}

3. Handle Push When App Opens

Future<void> _handlePushNotification() async {
  final data = await TelnyxClient.getPushMetaData();
  if (data != null) {
    PushMetaData pushMetaData = PushMetaData.fromJson(data);
    telnyxClient.handlePushNotification(
      pushMetaData,
      credentialConfig,
      tokenConfig,
    );
  }
}

Early Accept/Decline Handling

bool _waitingForInvite = false;

void acceptCall() {
  if (_incomingInvite != null) {
    _currentCall = telnyxClient.acceptCall(...);
  } else {
    // Set flag if invite hasn't arrived yet
    _waitingForInvite = true;
  }
}

// In socket message handler:
case SocketMethod.INVITE:
  _incomingInvite = message.message.inviteParams;
  if (_waitingForInvite) {
    acceptCall();  // Accept now that invite arrived
    _waitingForInvite = false;
  }
  break;

Push Notifications - iOS (APNS + PushKit)

1. AppDelegate Setup

// AppDelegate.swift
func pushRegistry(_ registry: PKPushRegistry,
                  didUpdate credentials: PKPushCredentials,
                  for type: PKPushType) {
    let deviceToken = credentials.token.map {
        String(format: "%02x", $0)
    }.joined()
    SwiftFlutterCallkitIncomingPlugin.sharedInstance?
        .setDevicePushTokenVoIP(deviceToken)
}

func pushRegistry(_ registry: PKPushRegistry,
                  didReceiveIncomingPushWith payload: PKPushPayload,
                  for type: PKPushType,
                  completion: @escaping () -> Void) {
    guard type == .voIP else { return }

    if let metadata = payload.dictionaryPayload["metadata"] as? [String: Any] {
        let callerName = (metadata["caller_name"] as? String) ?? ""
        let callerNumber = (metadata["caller_number"] as? String) ?? ""
        let callId = (metadata["call_id"] as? String) ?? UUID().uuidString

        let data = flutter_callkit_incoming.Data(
            id: callId,
            nameCaller: callerName,
            handle: callerNumber,
            type: 0
        )
        data.extra = payload.dictionaryPayload as NSDictionary

        SwiftFlutterCallkitIncomingPlugin.sharedInstance?
            .showCallkitIncoming(data, fromPushKit: true)
    }
}

2. Handle in Flutter

FlutterCallkitIncoming.onEvent.listen((CallEvent? event) {
  switch (event!.event) {
    case Event.actionCallIncoming:
      PushMetaData? pushMetaData = PushMetaData.fromJson(
        event.body['extra']['metadata']
      );
      telnyxClient.handlePushNotification(
        pushMetaData,
        credentialConfig,
        tokenConfig,
      );
      break;
    case Event.actionCallAccept:
      // Handle accept
      break;
  }
});

Handling Late Notifications

const CALL_MISSED_TIMEOUT = 60;  // seconds

void handlePushMessage(RemoteMessage message) {
  DateTime now = DateTime.now();
  Duration? diff = now.difference(message.sentTime!);

  if (diff.inSeconds > CALL_MISSED_TIMEOUT) {
    showMissedCallNotification(message);
    return;
  }

  // Handle normal incoming call...
}

Call Quality Metrics

Enable with debug: true in config:

// When making a call
call.newInvite(
  callerName: 'John',
  callerNumber: '+15551234567',
  destinationNumber: '+15559876543',
  clientState: 'state',
  debug: true,
);

// Listen for quality updates
call.onCallQualityChange = (CallQualityMetrics metrics) {
  print('MOS: ${metrics.mos}');
  print('Jitter: ${metrics.jitter * 1000} ms');
  print('RTT: ${metrics.rtt * 1000} ms');
  print('Quality: ${metrics.quality}');  // excellent, good, fair, poor, bad
};
Quality LevelMOS Range
excellent> 4.2
good4.1 - 4.2
fair3.7 - 4.0
poor3.1 - 3.6
bad≤ 3.0

AI Agent Integration

Connect to a Telnyx Voice AI Agent:

1. Anonymous Login

try {
  await telnyxClient.anonymousLogin(
    targetId: 'your_ai_assistant_id',
    targetType: 'ai_assistant',  // Default
    targetVersionId: 'optional_version_id',  // Optional
  );
} catch (e) {
  print('Login failed: $e');
}

2. Start Conversation

telnyxClient.newInvite(
  'User Name',
  '+15551234567',
  '',  // Destination ignored for AI Agent
  'state',
  customHeaders: {
    'X-Account-Number': '123',  // Maps to {{account_number}}
    'X-User-Tier': 'premium',   // Maps to {{user_tier}}
  },
);

3. Receive Transcripts

telnyxClient.onTranscriptUpdate = (List<TranscriptItem> transcript) {
  for (var item in transcript) {
    print('${item.role}: ${item.content}');
    // role: 'user' or 'assistant'
    // content: transcribed text
    // timestamp: when received
  }
};

// Get current transcript anytime
List<TranscriptItem> current = telnyxClient.transcript;

// Clear transcript
telnyxClient.clearTranscript();

4. Send Text to AI Agent

Call? activeCall = telnyxClient.calls.values.firstOrNull;

if (activeCall != null) {
  activeCall.sendConversationMessage(
    'Hello, I need help with my account'
  );
}

Custom Logging

class MyCustomLogger extends CustomLogger {
  @override
  log(LogLevel level, String message) {
    print('[$level] $message');
    // Send to analytics, file, server, etc.
  }
}

final config = CredentialConfig(
  // ... other config
  logLevel: LogLevel.debug,
  customLogger: MyCustomLogger(),
);

Troubleshooting

IssueSolution
No audio on AndroidCheck RECORD_AUDIO permission
No audio on iOSCheck NSMicrophoneUsageDescription in Info.plist
Push not working (debug)Push only works in release mode
Login failsVerify SIP credentials in Telnyx Portal
10-second timeoutINVITE didn't arrive - check network/push setup
sender_id_mismatchFCM project mismatch between app and server

references/webrtc-server-api.md has the server-side WebRTC API — credential creation, token generation, and push notification setup. You MUST read it when setting up authentication or push notifications.

API Reference

TxClient

Telnyx Client

TelnyxClient() is the core class of the SDK, and can be used to connect to our backend socket connection, create calls, check state and disconnect, etc.

    TelnyxClient _telnyxClient = TelnyxClient();

Logging into Telnyx Client

To log into the Telnyx WebRTC client, you'll need to authenticate using a Telnyx SIP Connection. Follow our quickstart guide to create JWTs (JSON Web Tokens) to authenticate. To log in with a token we use the connectWithToken() method. You can also authenticate directly with the SIP Connection username and password with the connectWithCredential() method:

    _telnyxClient.connectWithToken(tokenConfig)
                     //OR
    _telnyxClient.connectWithCredential(credentialConfig)

Listening for events and reacting - Accepting a Call

In order to be able to accept a call, we first need to listen for invitations. We do this by getting the Telnyx Socket Response callbacks from our TelnyxClient:

Call

Call

The Call class is used to manage the call state and call actions. It is used to accept, decline, end, mute, hold, and send DTMF tones during a call.

Accept Call

In order to accept a call, we simply retrieve the instance of the call and use the.acceptCall(callID) method:

    _telnyxClient.call.acceptCall(_incomingInvite?.callID);

Decline / End Call

In order to end a call, we can get a stored instance of Call and call the.endCall(callID) method. To decline an incoming call we first create the call with the.createCall() method and then call the.endCall(callID) method:

    if (_ongoingCall) {
      _telnyxClient.call.endCall(_telnyxClient.call.callId);
    } else {
      _telnyxClient.createCall().endCall(_incomingInvite?.callID);
    }

DTMF (Dual Tone Multi Frequency)

In order to send a DTMF message while on a call you can call the.dtmf(callID, tone), method where tone is a String value of the character you would like pressed:

    _telnyxClient.call.dtmf(_telnyxClient.call.callId, tone);

Mute a call

To mute a call, you can simply call the.onMuteUnmutePressed() method:

    _telnyxClient.call.onMuteUnmutePressed();

Toggle loud speaker

To toggle loud speaker, you can simply call.enableSpeakerPhone(bool):

    _telnyxClient.call.enableSpeakerPhone(true);

Put a call on hold

To put a call on hold, you can simply call the.onHoldUnholdPressed() method:

    _telnyxClient.call.onHoldUnholdPressed();

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

35.06%
按下载量换算71

Claude

30.78%
按下载量换算62

Cursor

17.67%
按下载量换算36

Gemini CLI

10.3%
按下载量换算21

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

可疑

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在 warning/failed 结果,不能写成本站确认安全。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills