flutter_baidu_speech_tts

English | 中文


English

A Flutter plugin for Baidu Text-to-Speech (TTS) that supports online, offline and mixed (MIX) synthesis.

Platform support:

  • Android: online / offline / mixed synthesis. Supports accessToken, apiKey + secretKey and iamKey authentication.
  • iOS: online / offline / mixed synthesis. Supports accessToken, apiKey + secretKey and iamKey authentication. Physical devices only (the SDK static library ships an arm64 device slice only; simulator architectures are excluded in the podspec).
  • OHOS (HarmonyOS): online / offline / mixed synthesis. Supports accessToken and apiKey + secretKey. iamKey and offlineOverwriteAssets do not apply; if passed, they are listed under ignoredParams in the initialize return value. Offline models are loaded directly from the path under context.resourceDir that maps to resources/resfile/, with no copy.

1. Prerequisites

Create an app on the Baidu AI Speech platform to obtain:

  • Online synthesis: apiKey + secretKey (or accessToken)
  • Offline synthesis: additionally appId + authSn
  • Offline model files (.dat, 8–16MB each): text model + acoustic model. Not shipped with the plugin — download them yourself.

Note: authSn is bound to your app's package name / Bundle ID. The three platforms (Android / iOS / OHOS) each require separate app registration; the credentials are independent per platform. The recommended approach is to dispatch credentials by platform on the Dart side (see lib/utils/tts_config.dart in the example).

2. Add dependency

pubspec.yaml:

dependencies:
  flutter_baidu_speech_tts: ^1.0.0

Then flutter pub get. Native registration on all three platforms is auto-generated by the Flutter toolchain — no manual wiring needed:

  • Android: GeneratedPluginRegistrant.java registers com.baidu.flutter.tts.FlutterBaiduTtsPlugin
  • iOS: pod install generates the flutter_baidu_speech_tts pod
  • OHOS: GeneratedPluginRegistrant.ets registers FlutterBaiduTtsPlugin and injects com.baidu.tts_*.har into entry dependencies

Demo

Place your screenshots in the same directory as this README and the images will render automatically.


Before initialization — the TTS config page where credentials are entered

Initialization success — engine loaded and code is 0

Synthesizing / speaking — text is being converted to speech and played

3. Quick start

final tts = FlutterBaiduTts();

// typedEvents is a broadcast stream; subscribers cancel on their own.
final sub = tts.typedEvents.listen((BaiduTtsEvent e) {
  debugPrint('$e');
  // Synthesized data chunk: e.event == 'SYNTHESIZE_DATA_ARRIVED', PCM in e.audioData
});

final init = await tts.initializeWithConfig(const BaiduTtsConfig(
  apiKey: 'ak',
  secretKey: 'sk',
));
if (init.isSuccess) {
  await tts.speakText('Hello, Baidu speech synthesis');
}

// On page dispose
await sub.cancel();
await tts.releaseTts();

Credential management

Reference lib/utils/tts_config.dart in the example: dispatch credentials by Platform.isAndroid / isIOS, then produce a unified BaiduTtsConfig:

static BaiduTtsConfig buildInitConfig() {
  return BaiduTtsConfig(
    apiKey: _apiKey,
    secretKey: _secretKey,
    onlineSpeaker: '4100',
    onlineTimeoutMs: 2000,
    enableOffline: true,
    // The following 4 items are only needed for offline synthesis
    appId: _appId,
    authSn: _authSn,
    offlineTextModelAsset: 'bd_etts_common_text_txt_all_..._v6.0.0_20240731.dat',
    offlineSpeechModelAsset: 'bd_etts_common_speech_duxiaomei_..._20251031153737.dat',
  );
}

Key points:

  • offlineTextModelAsset / offlineSpeechModelAsset take file names, not paths; the plugin resolves them per platform
  • If you download models to disk yourself, use offlineTextModelPath / offlineSpeechModelPath with absolute paths — they take precedence over asset names
  • Do not commit real credentials to a public repo

Full call flow

final FlutterBaiduTts _tts = FlutterBaiduTts();

// 1) Subscribe first (broadcast stream, multi-listener, self-cancel)
_sub = _tts.typedEvents.listen((BaiduTtsEvent e) {
  // e.audioData contains PCM chunks when e.event == 'SYNTHESIZE_DATA_ARRIVED'
});

// 2) Initialize
final init = await _tts.initializeWithConfig(TtsConfig.buildInitConfig());
if (!init.isSuccess) {
  // init.code / init.message; when offline is enabled, also init.offlineCode / offlineMessage
}

// 3) Synthesize & play / synthesize only
await _tts.speakText(text, mode: BaiduTtsMode.offline); // online / offline / mix, default mix
await _tts.synthesizeText(text);

// 4) Control & release
await _tts.pauseTts();
await _tts.resumeTts();
await _tts.stopTts();
await _sub.cancel();
await _tts.releaseTts();

getCuid() returns the SDK device fingerprint, used to apply for offline authorization on the Baidu platform. It typically has a value only after initializeWithConfig, so refresh it once initialization completes.

Error handling contract

Every method returns a result of the form {code, message, ...}. On failure code != 0; no PlatformException is thrown — do not use try/catch to judge success; use isSuccess instead. Reserved negative codes:

  • -1: general error (missing parameter, not initialized, SDK threw, etc.)
  • -2: initialize already in progress (concurrent call)

All other non-zero values come from the Baidu SDK error codes (Android: getDetailCode(), iOS: NSError.code). When initialize fails, the return value also carries offlineCode / offlineMessage (offline engine load result) and paramErrors (details for individual parameters the SDK rejected).

For the raw Map return value, use FlutterBaiduTtsPlatform.instance directly.

4. Offline models

Offline models (.dat, 8–16MB each, ~56MB in total) are Baidu proprietary licensed files. They are not shipped with the plugin. Offline synthesis requires the integrator to obtain them from the Baidu AI Speech platform, place them in the corresponding native resource directory, and reference them by file name (not path):

await tts.initializeWithConfig(BaiduTtsConfig(
  apiKey: 'ak',
  secretKey: 'sk',
  appId: 'appId',
  authSn: 'authSn',
  enableOffline: true,
  offlineTextModelAsset: 'bd_etts_common_text_txt_all_mand_eng_middle_big_v6.0.0_20240731.dat',
  offlineSpeechModelAsset:
      'bd_etts_common_speech_duxiaoyu_mand_eng_high_am-tac-csubgan16k_v4.9.0_20240918_20251031153737.dat',
));

Placement directory per platform:

  • Android: android/app/src/main/assets/ (copied to filesDir on first initialize; offlineOverwriteAssets: true forces overwrite)
  • iOS: added to the Xcode Runner target (goes into Bundle.main)
  • OHOS: entry/src/main/resources/resfile/ (resolved to context.resourceDir, no copy)

You can also download models to disk yourself and pass absolute paths via offlineTextModelPath / offlineSpeechModelPath, which take precedence over asset names. If a path does not exist, initialize returns failure directly and does not silently fall back.

5. Android integration

Minimal changes — the android/ directory is mostly template defaults:

  • Permissions: the plugin's own manifest already declares INTERNET and ACCESS_NETWORK_STATE, which merge into the host — no need to redeclare. Optional: READ_PHONE_STATE (for a more stable cuid; Android 10+ can no longer obtain IMEI so declare only if needed), READ_EXTERNAL_STORAGE (only when models live outside the app sandbox)
  • applicationId: must match the package name registered on the Baidu platform
  • minSdk / targetSdk / ndkVersion: use the flutter.* defaults; the SDK's jars (in android/libs/) and .so files (in android/src/main/jniLibs/, covering arm64-v8a / armeabi-v7a / x86 / x86_64) are bundled inside the plugin AAR — no extra repositories or abiFilters needed
  • Proguard: rules are shipped via consumerProguardFiles (android/consumer-rules.pro), so no extra configuration is needed when minifyEnabled is on

Offline models go into:

android/app/src/main/assets/
  bd_etts_common_text_txt_all_mand_eng_middle_big_v6.0.0_20240731.dat   # text model
  bd_etts_common_speech_duxiaomei_..._20251031153737.dat                # acoustic model

6. iOS integration

Physical devices only — the Baidu static library has an arm64 device slice only; the podspec excludes simulators via EXCLUDED_ARCHS[sdk=iphonesimulator*].

  1. Static library libBDSpeechTTSBaseKit.a (~239MB): not shipped with the plugin. During pod install, the podspec auto-downloads it to ios/Libs/ when missing (override URL with the FLUTTER_BAIDU_TTS_IOS_LIB_URL environment variable). Linking is handled by Pods-Runner.xcconfig: OTHER_LDFLAGS includes -ObjC -l"BDSpeechTTSBaseKit", LIBRARY_SEARCH_PATHS points to .symlinks/plugins/flutter_baidu_speech_tts/ios/Libs. If the download fails or you prefer manual management, copy BDSClientLib/libBDSpeechTTSBaseKit.a from the Baidu iOS TTS SDK package (BDSpeechClientSDK_TTS) into ios/Libs/.

  2. Offline models: add the .dat files to the Runner target's Resources (they end up in Bundle.main). To avoid duplicating repo weight, the example project references the Android assets directory directly: in ios/Runner.xcodeproj/project.pbxproj, the .dat files' path values point to ../android/app/src/main/assets/xxx.dat and are added to PBXResourcesBuildPhase. In Xcode, drag the files in and check the Runner target.

    Model path resolution order: offlineXxxModelPath (absolute path) → Bundle.main → sandbox Documents/. If a model is not found or loadOfflineEngine fails, initialize returns failure with offlineCode / offlineMessage — it does not silently downgrade to online.

  3. ios/Runner/Info.plist: add NSLocalNetworkUsageDescription if needed (e.g. "This app needs to access the local network"). TTS only plays audio — no microphone permission required.

  4. Deployment target: IPHONEOS_DEPLOYMENT_TARGET = 12.0. The Podfile uses the Flutter default (no explicit platform).

  5. Audio session: managed by the SDK itself (the plugin sets the category to playback). If the host needs to manage AVAudioSession, override it after initialize.

Warning: do not manually link a static library from outside the project tree (e.g. an absolute path like ../../BDSpeechClientSDK_.../BDSClientLib/libBDSpeechTTSBaseKit.a). This is a machine-specific debug leftover — the plugin's pod already handles linking the same library. It will break on a different machine or directory. If your project has such a File Reference, remove it.

7. OHOS (HarmonyOS) integration

  1. Declare network permissions yourself. The HAR's module.json5 is not part of the final build, and the permissions it declares are not merged into the host app. Add them to ohos/entry/src/main/module.json5:
"requestPermissions": [
  { "name": "ohos.permission.INTERNET" },
  { "name": "ohos.permission.GET_NETWORK_INFO" }
]
 products下需要配置:"buildOption": {
            "strictMode": {
            "useNormalizedOHMUrl": true
          }

Without INTERNET, the online authentication during TTS initialization (PARAM_LICENSE_URL) fails and synthesis is unavailable. If your test module (ohosTest) also has networking cases, declare them there too.

  1. Offline models: place under entry/src/main/resources/resfile/ and pass the file name via offlineTextModelAsset / offlineSpeechModelAsset (it resolves to a path under context.resourceDir, with no copy).

  2. Dependencies: com.baidu.tts_*.har + authbaselibrary.har are injected by the Flutter toolchain from the plugin's ohos/libs/ into entry (see ohos/entry/oh-package-lock.json5) — no need to manually write oh-package.json5.

  3. SDK version: example uses compatibleSdkVersion 5.0.4(16), runtimeOS HarmonyOS (ohos/build-profile.json5).

  4. Limitations: iamKey and offlineOverwriteAssets are not supported; passing them lists them under ignoredParams in the initialize return value. The offline license URL is fixed at https://upl.baidu.com/auth and is not configurable.

8. Running the example

Credentials are centralized in example/lib/utils/tts_config.dart (TtsConfig), split into Android / iOS / OHOS groups by platform. Before running, replace apiKey / secretKey / appId / authSn with your own:

cd example
flutter run            # Android
flutter run -d <device>  # iOS, simulator not supported

Note: these credentials are plain-text constants, only for running the example locally. Do not commit real credentials to a public repo.

9. Integration checklist

  • Add dependency in pubspec.yaml, run flutter pub get
  • Package name / Bundle ID matches Baidu platform registration on all three platforms; appId / authSn are per-platform
  • Android: models placed in android/app/src/main/assets/
  • iOS: models added to Runner target Resources; run on device; after pod install confirm ios/Libs/libBDSpeechTTSBaseKit.a exists
  • OHOS: models placed in entry/src/main/resources/resfile/; module.json5 declares ohos.permission.INTERNET
  • Subscribe to typedEvents before calling initializeWithConfig
  • Use result.isSuccess to judge success; for offline failures check offlineCode / offlineMessage
  • On page dispose: sub.cancel() + releaseTts()

10. FAQ / Troubleshooting

  • initialize returns code != 0: check message and paramErrors (which parameters the SDK rejected). For offline issues, check offlineCode / offlineMessage.
  • Offline doesn't work but online is fine: model file name is misspelled, model not placed in the correct resource directory, or appId / authSn missing. With mode: BaiduTtsMode.offline, there is no fallback to online; mix mode falls back to online when offline fails.
  • iOS simulator architecture error: expected behavior — the static library has no simulator slice; use a physical device.
  • OHOS: no sound / init failure: check ohos.permission.INTERNET in the entry module first.
  • getCuid() returns empty: call initializeWithConfig first, then retrieve.

11. Known limitations

  • The iOS static library is 239MB, exceeding pub.dev's 100MB per-package limit, so it is not shipped with the package and is downloaded automatically during pod install (override with FLUTTER_BAIDU_TTS_IOS_LIB_URL).
  • iOS supports physical devices only (the static library has no simulator slice).
  • When upgrading the native SDK, re-check its transitive dependencies: after unpacking on Android there is no dependency metadata, so the OkHttp used internally by the SDK is declared explicitly in android/build.gradle.
  • The OHOS offline license URL is currently fixed at https://upl.baidu.com/auth and is not configurable.
  • On Android the SDK's loadAudioPlayer() is not called; playback uses the SDK's default player.

中文

一个 Flutter 百度语音合成(TTS)插件,支持在线、离线和混合(MIX)合成。

平台支持:

  • Android:在线 / 离线 / 混合合成。支持 accessTokenapiKey + secretKeyiamKey 三种鉴权方式。
  • iOS:在线 / 离线 / 混合合成。支持 accessTokenapiKey + secretKeyiamKey 三种鉴权方式。仅支持真机(SDK 静态库仅包含 arm64 真机架构, podspec 中已排除模拟器架构)。
  • OHOS(鸿蒙):在线 / 离线 / 混合合成。支持 accessTokenapiKey + secretKeyiamKeyofflineOverwriteAssets 不适用;若传入, 会在 initialize 返回值的 ignoredParams 中列出。离线模型直接从 context.resourceDir(映射到 resources/resfile/)下的路径加载,不做拷贝。

1. 前置准备

百度语音开放平台创建应用,拿到:

  • 在线合成apiKey + secretKey(或 accessToken
  • 离线合成:额外需要 appId + authSn
  • 离线模型文件.dat,单个 8~16MB):文本模型 + 音库模型。插件不附带 模型,需自行下载放入工程

注意:authSn 与应用包名/BundleId 绑定,三端(Android / iOS / OHOS)需各自 注册应用,鉴权信息互相独立。推荐做法是在 Dart 侧按平台分发(见示例 lib/utils/tts_config.dart)。

2. 添加依赖

pubspec.yaml

dependencies:
  flutter_baidu_speech_tts: ^1.0.0

然后 flutter pub get。三端的原生注册都由 Flutter 工具自动生成,无需手写:

  • AndroidGeneratedPluginRegistrant.java 注册 com.baidu.flutter.tts.FlutterBaiduTtsPlugin
  • iOSpod install 生成 flutter_baidu_speech_tts pod
  • OHOSGeneratedPluginRegistrant.ets 注册 FlutterBaiduTtsPlugin,并把 com.baidu.tts_*.har 注入 entry 依赖

功能演示

请将截图放置在本 README 同级目录下,图片会自动渲染。


初始化前 — 输入 TTS 凭据的配置页面

初始化成功 — 引擎加载完成,code 为 0表示成功

正在合成/播放 — 文本正在转换为语音并播放

3. 快速开始

final tts = FlutterBaiduTts();

// typedEvents 是一个广播流;订阅者需自行取消订阅。
final sub = tts.typedEvents.listen((BaiduTtsEvent e) {
  debugPrint('$e');
  // 合成数据回调:e.event == 'SYNTHESIZE_DATA_ARRIVED',PCM 数据在 e.audioData 中
});

final init = await tts.initializeWithConfig(const BaiduTtsConfig(
  apiKey: 'ak',
  secretKey: 'sk',
));
if (init.isSuccess) {
  await tts.speakText('Hello, Baidu speech synthesis');
}

// 页面销毁时
await sub.cancel();
await tts.releaseTts();

凭据与参数集中管理

参考 lib/utils/tts_config.dart:按 Platform.isAndroid / isIOS 分发三端凭据, 最后统一产出 BaiduTtsConfig

static BaiduTtsConfig buildInitConfig() {
  return BaiduTtsConfig(
    apiKey: _apiKey,
    secretKey: _secretKey,
    onlineSpeaker: '4100',
    onlineTimeoutMs: 2000,
    enableOffline: true,
    // 以下 4 项仅离线合成需要
    appId: _appId,
    authSn: _authSn,
    offlineTextModelAsset: 'bd_etts_common_text_txt_all_..._v6.0.0_20240731.dat',
    offlineSpeechModelAsset: 'bd_etts_common_speech_duxiaomei_..._20251031153737.dat',
  );
}

关键点:

  • offlineTextModelAsset / offlineSpeechModelAsset 传的是文件名,不是路径; 插件在各端按自己的规则解析
  • 如果模型是自己下载到磁盘的,用 offlineTextModelPath / offlineSpeechModelPath 传绝对路径,优先级高于 asset 名
  • 不要把真实凭据提交到公开仓库

完整调用流程

final FlutterBaiduTts _tts = FlutterBaiduTts();

// 1) 先订阅事件(广播流,可多次监听,自行 cancel)
_sub = _tts.typedEvents.listen((BaiduTtsEvent e) {
  // e.event == 'SYNTHESIZE_DATA_ARRIVED' 时 e.audioData 为 PCM 分片
});

// 2) 初始化
final init = await _tts.initializeWithConfig(TtsConfig.buildInitConfig());
if (!init.isSuccess) {
  // init.code / init.message;启用离线时还有 init.offlineCode / offlineMessage
}

// 3) 合成播放 / 只合成
await _tts.speakText(text, mode: BaiduTtsMode.offline); // online / offline / mix,默认 mix
await _tts.synthesizeText(text);

// 4) 控制与释放
await _tts.pauseTts();
await _tts.resumeTts();
await _tts.stopTts();
await _sub.cancel();
await _tts.releaseTts();

getCuid() 返回 SDK 设备指纹,用于在百度平台申请离线授权;通常要在 initializeWithConfig 之后才有值,所以初始化完成后需再取一次。

错误处理约定

每个方法都返回形如 {code, message, ...} 的结果对象。失败时 code != 0, 不会抛出 PlatformException —— 不要用 try/catch 判断成败,用 isSuccess。 保留的负数错误码:

  • -1:通用错误(参数缺失、未初始化、SDK 内部异常等)
  • -2initialize 正在进行中(并发调用)

其余非零值来自百度 SDK 错误码(Android:getDetailCode(),iOS: NSError.code)。当 initialize 失败时,返回值还会携带 offlineCode / offlineMessage(离线引擎加载结果)和 paramErrors(SDK 拒绝的各个参数的 详细信息)。

如需获取原始 Map 返回值,请直接使用 FlutterBaiduTtsPlatform.instance

4. 离线模型

离线模型(.dat 文件,单个 8–16MB,共约 56MB)是百度专有授权文件不随插件分发。离线合成需要接入方从 百度 AI 语音平台 获取模型文件,放置到 自己项目的对应原生资源目录中,并通过 offlineTextModelAsset / offlineSpeechModelAsset文件名(而非路径)引用:

await tts.initializeWithConfig(BaiduTtsConfig(
  apiKey: 'ak',
  secretKey: 'sk',
  appId: 'appId',
  authSn: 'authSn',
  enableOffline: true,
  offlineTextModelAsset: 'bd_etts_common_text_txt_all_mand_eng_middle_big_v6.0.0_20240731.dat',
  offlineSpeechModelAsset:
      'bd_etts_common_speech_duxiaoyu_mand_eng_high_am-tac-csubgan16k_v4.9.0_20240918_20251031153737.dat',
));

各平台放置目录:

  • Androidandroid/app/src/main/assets/(插件首次 initialize 时拷贝到 filesDirofflineOverwriteAssets: true 可强制覆盖)
  • iOS:添加到 Xcode Runner target(进入 Bundle.main
  • OHOSentry/src/main/resources/resfile/(解析为 context.resourceDir 下的路径,不做拷贝)

你也可以自行将模型下载到磁盘,并通过 offlineTextModelPath / offlineSpeechModelPath 传入绝对路径,路径优先级高于文件名。如果路径不存在, initialize 直接返回失败,不会静默回退。

5. Android 集成

改动很少,android/ 下基本是模板默认值:

  • 权限:插件自身的 manifest 已声明 INTERNETACCESS_NETWORK_STATE, 会 merge 进宿主,宿主无需再声明。可选补充 READ_PHONE_STATE(让 cuid 更 稳定;Android 10+ 已无法获取 IMEI,仅在需要时声明)、READ_EXTERNAL_STORAGE (模型放在沙箱外时)
  • applicationId:必须与百度平台注册的包名一致
  • minSdk / targetSdk / ndkVersion:沿用 flutter.* 默认值;SDK 的 jar 包 (在 android/libs/)与 .so 文件(在 android/src/main/jniLibs/,覆盖 arm64-v8a / armeabi-v7a / x86 / x86_64)已打进插件 AAR,不需要额外声明仓库 或 abiFilters
  • 混淆:规则由插件 consumerProguardFilesandroid/consumer-rules.pro) 提供,开 minifyEnabled 也不用额外配置

离线模型放到:

android/app/src/main/assets/
  bd_etts_common_text_txt_all_mand_eng_middle_big_v6.0.0_20240731.dat   # 文本模型
  bd_etts_common_speech_duxiaomei_..._20251031153737.dat                # 音库模型

6. iOS 集成

仅支持真机 —— 百度 iOS 静态库只有 arm64 device slice,podspec 里 EXCLUDED_ARCHS[sdk=iphonesimulator*] 排除了模拟器。

  1. 静态库 libBDSpeechTTSBaseKit.a(约 239MB):不随插件发布,pod install 时 podspec 会自动下载到插件的 ios/Libs/(可用环境变量 FLUTTER_BAIDU_TTS_IOS_LIB_URL 覆盖下载地址)。链接由 Pods-Runner.xcconfig 完成:OTHER_LDFLAGS-ObjC -l"BDSpeechTTSBaseKit"LIBRARY_SEARCH_PATHS 指向 .symlinks/plugins/flutter_baidu_speech_tts/ios/Libs。如果下载失败或希望 手动管理,请从百度 iOS TTS SDK 包(BDSpeechClientSDK_TTS)中将 BDSClientLib/libBDSpeechTTSBaseKit.a 拷贝到 ios/Libs/

  2. 离线模型加入 Runner target 的 Resources(进 Bundle.main)。本工程为 避免重复占用体积,直接引用了 Android 的 assets 目录: ios/Runner.xcodeproj/project.pbxproj.datpath 均为 ../android/app/src/main/assets/xxx.dat,并加入了 PBXResourcesBuildPhase。 用 Xcode 拖入并勾选 Runner target 即可。

    模型路径解析顺序:offlineXxxModelPath 绝对路径 → Bundle.main → 沙箱 Documents/。找不到或 loadOfflineEngine 失败时 initialize 直接返回失败, 不会静默降级为在线。

  3. ios/Runner/Info.plist:本工程加了 NSLocalNetworkUsageDescription ("此应用需要访问本地网络以支持相关功能")。TTS 只播放不录音,不需要麦克风 权限

  4. 部署版本IPHONEOS_DEPLOYMENT_TARGET = 12.0Podfile 未显式指定 platform,用 Flutter 默认。

  5. 音频会话:由 SDK 自己管理(插件把 category 设为 playback)。宿主若要 自己管 AVAudioSession,在 initialize 之后再覆盖。

注意:不要手工链接工程外的静态库(如 ../../BDSpeechClientSDK_.../BDSClientLib/libBDSpeechTTSBaseKit.a 这样的绝对 路径)。这是本机调试遗留的依赖,插件的 pod 已经负责链接同名库,换机器/换目录 会直接编译失败。如果工程中有此类 File Reference,建议清理掉。

7. OHOS(鸿蒙)集成

  1. 必须自己声明网络权限。HAR 的 module.json5 不参与最终构建,其权限不会 merge 到宿主。ohos/entry/src/main/module.json5
"requestPermissions": [
  { "name": "ohos.permission.INTERNET" },
  { "name": "ohos.permission.GET_NETWORK_INFO" }
]
 products下需要配置:"buildOption": {
            "strictMode": {
            "useNormalizedOHMUrl": true
          }

INTERNET 会导致初始化阶段的在线授权(PARAM_LICENSE_URL)失败,合成 完全不可用。ohosTest 里若有联网用例也要声明。

  1. 离线模型放到 entry/src/main/resources/resfile/,传文件名即可;插件解析 到 context.resourceDir 下的路径,不做复制

  2. 依赖com.baidu.tts_*.har + authbaselibrary.har 由 Flutter 工具从 插件的 ohos/libs/ 注入 entry(见 ohos/entry/oh-package-lock.json5), 无需手写 oh-package.json5 依赖。

  3. SDK 版本:示例工程 compatibleSdkVersion5.0.4(16)runtimeOSHarmonyOSohos/build-profile.json5)。

  4. 限制:不支持 iamKeyofflineOverwriteAssets,传了会在 initialize 返回值的 ignoredParams 里列出。离线授权 URL 固定为 https://upl.baidu.com/auth,不可配置。

8. 运行示例

示例的凭据集中在 example/lib/utils/tts_config.dartTtsConfig)中,按平台 分为 Android / iOS / OHOS 三组。运行前,请将 apiKey / secretKey / appId / authSn 替换为你自己的凭据:

cd example
flutter run            # Android
flutter run -d <device>  # iOS,不支持模拟器

注意:这些凭据目前为明文常量,仅用于本地运行示例。请勿将真实凭据提交到 公开仓库。

9. 接入自检清单

  • pubspec.yaml 加依赖,flutter pub get
  • 三端包名/BundleId 与百度平台注册一致,appId / authSn 按端区分
  • Android 模型放 android/app/src/main/assets/
  • iOS 模型加入 Runner target Resources;真机运行;pod install 后确认 ios/Libs/libBDSpeechTTSBaseKit.a 存在
  • OHOS 模型放 entry/src/main/resources/resfile/module.json5 声明 ohos.permission.INTERNET
  • 先订阅 typedEventsinitializeWithConfig
  • result.isSuccess 判断成败,离线失败看 offlineCode / offlineMessage
  • 页面销毁时 sub.cancel() + releaseTts()

10. 常见问题

  • 初始化返回 code != 0:先看 messageparamErrors(SDK 拒绝的具体 参数)。离线相关看 offlineCode / offlineMessage
  • 离线不生效但在线正常:模型文件名拼错、模型没放进对应资源目录、或 appId / authSn 缺失。mode: BaiduTtsMode.offline 时不会回落在线,mix 才会在线 优先失败回落。
  • iOS 模拟器报架构错误:预期行为,静态库无模拟器 slice,只能真机。
  • OHOS 合成无声/初始化失败:优先检查 entry 模块的 ohos.permission.INTERNET
  • getCuid() 返回空:先 initializeWithConfig 再取。
  • ** 对于ios如若pod install失败,注意参考:https://cloud.baidu.com/doc/SPEECH/s/wltwwnvc9#5-sdk%E9%9B%86%E6%88%90 官网的教程导入下资源到项目中使用即可