tencent_asr_probe.dart 2.21 KB
import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:crypto/crypto.dart';
import 'package:web_socket_channel/web_socket_channel.dart';

Future<void> main(List<String> args) async {
  const secretId = 'AKID9Vgy8FEC5qSxLcllVCmXzJWaVSI0Z2Nb';
  const secretKey = 'c2c5MTOBo5d9XilhaLzVSG4DE7qRuCJF';
  const appId = '1308375824';

  final int now = DateTime.now().millisecondsSinceEpoch ~/ 1000;
  final String voiceId = 'probe_${DateTime.now().microsecondsSinceEpoch}';
  final Map<String, String> params = <String, String>{
    'secretid': secretId,
    'timestamp': '$now',
    'expired': '${now + 86400}',
    'nonce': '${(DateTime.now().microsecondsSinceEpoch % 999999999).abs() + 1}',
    'engine_model_type': '16k_zh',
    'voice_id': voiceId,
    'voice_format': '1',
    'needvad': '1',
    'filter_modal': '1',
    'filter_punc': '1',
    'convert_num_mode': '1',
  };

  final sorted = params.entries.toList()
    ..sort((a, b) => a.key.compareTo(b.key));
  final canonical = sorted.map((e) => '${e.key}=${e.value}').join('&');
  final signText = 'asr.cloud.tencent.com/asr/v2/$appId?$canonical';
  final digest = Hmac(sha1, utf8.encode(secretKey))
      .convert(utf8.encode(signText))
      .bytes;
  final signature = base64.encode(digest);
  final query = sorted
      .map((e) => '${e.key}=${Uri.encodeQueryComponent(e.value)}')
      .join('&');
  final uri = Uri.parse(
      'wss://asr.cloud.tencent.com/asr/v2/$appId?$query&signature=${Uri.encodeQueryComponent(signature)}');

  stdout.writeln('signText=$signText');
  stdout.writeln('signature=$signature');
  stdout.writeln('url=$uri');

  final channel = WebSocketChannel.connect(uri);
  final completer = Completer<void>();
  channel.stream.listen(
    (dynamic m) {
      stdout.writeln('RECV: $m');
      if (!completer.isCompleted) completer.complete();
    },
    onError: (Object e) {
      stdout.writeln('ERR: $e');
      if (!completer.isCompleted) completer.completeError(e);
    },
    onDone: () {
      stdout.writeln('DONE');
      if (!completer.isCompleted) completer.complete();
    },
  );

  await channel.ready.timeout(const Duration(seconds: 10));
  await completer.future.timeout(const Duration(seconds: 12));
  await channel.sink.close();
}