AudioPlayers 不适用于 iOS |颤振插件

AudioPlayers does not work on iOS | Flutter plugin

我正在创建一个 Flutter 插件。目前,代码:

  1. 将字符串合成为音频文件
  2. 获取文件路径
  3. 使用 audioplayers
  4. 播放音频文件

当我 运行 Android 中的应用程序时,它完美运行。然而,当我 运行 它在 iOS 上时,它没有(假设与 permissions/restrictions 相关)

await flutterTts
        .synthesizeToFile(
            "This is my first audio synthesizer in Flutter", audioFileName)
        .then((success) => {
              if (success == 1)
                {
                  print('Successfully synthesized!!'),

                  // Gets the path to the generated file depending on the platform
                  pathFile =
                      Platform.isAndroid ? pathToFileAndroid : pathToFileIos,
                  pathFile
                      .then((pathToAudioFile) => {
                            print('Path to file: ' + pathToAudioFile),
                            // Speakers/earpiece
                            // int result = await player.earpieceOrSpeakersToggle();
                            // Sets the path to the file
                            audioPlayer.setUrl(pathToAudioFile),
                            audioPlayer.setVolume(1.0),
                            // Gets the duration of the audio file to be reproduced
                            // Plays the audio file
                            playLocal(audioPlayer, pathToAudioFile),
                          }) // pathFile
                      .catchError((e) {
                    print('Error: Unable to get the path to the audio file');
                  }),
                }, // success
            }) //synthesizeToFile
        .catchError((e) {
      print('Error during the synthesisation: $e');
    });
  }




/// Gets the path to the file to be accessed (iOS)
  static Future<String> get pathToFileIos async {
    Directory appDocDir = await getApplicationDocumentsDirectory();
    String appDocPath = appDocDir.path;
    print('appDocPath: $appDocPath');
    return '$appDocPath/$audioFileName';
  }

我实施了 audioPlayer.onDurationChanged.listen 以确认文件路径是正确的(它实际上获取了文件的持续时间)。然而,文件没有播放。

我正在使用模拟器测试应用程序,这是文件存储的路径

/localPaty/Devices/deviceID/data/Containers/Data/Application/appID/Documents/temp_audio_cue.caf

我阅读了有关此主题的不同问题,但没有找到适合我的案例的解决方案

我试过:

按照文档的建议编辑传输安全性

   <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict> 

使用 AudioCache ()

大家还有什么建议吗?我是否需要将文件移动到我的本地资产并使用 AudioCache 来复制文件?

更新

我也试过添加标志isLocal

  playLocal() async {
    int result = await audioPlayer.play(localPath, isLocal: true);
  }

根据documentation是需要原因

The isLocal flag is required only because iOS and macOS make a difference about it

是returns1,所以我猜是成功了,但是还是没有触发声音。可能是模拟器失败了?

"iOS => call startHeadlessService, playerId ID"
"iOS => call setUrl, playerId ID"
"iOS => call setVolume, playerId ID"
"iOS => call play, playerId ID"
2021-02-03 11:59:33.149925+0100 Runner[61496:850044] flutter: Played successfully?: 1

我也测试过用错误的路径调用playLocal()。它一直返回 1 但之后显示以下错误:

FigFileForkOpenMainByCFURL signalled err=2 (errno) (open failed)

然而,使用正确的 localPath 调用方法不会触发错误,因此我认为它应该正确播放。

备注

如果我不调用 playLocal(),而是调用 flutter_tts.speak('test'),它会起作用。因此,错误应该可能与audioplayers.

有关

我使用的版本是flutter_tts ^2.1.0audioplayers: ^0.17.3

最后,我意识到问题与AVAudioSession及其会话管理有关。 flutter_ttsaudioplayers 这两个库都使用它,因此它们可以将它覆盖在其他地方。

我不得不将方法更改为以下内容:

 /// Synthesises the current audio cue into an audio file
  static Future<void> synthesiseStringToAudioFile() async {
    int synthesized = await flutterTts.synthesizeToFile(
        "This is my first audio synthesizer in Flutter", audioFileName);
    if (synthesized == 1) {
      String pathFile =
          await (Platform.isAndroid ? pathToFileAndroid : pathToFileIos);
      print('Path to file: ' + pathFile);
      playAudioFile(pathFile);
    } else {
      print('Error during the synthesisation');
    }
  }

开始触发 iOS 中的一些音频。尽管如此,通知中仍然存在一些问题,但我认为答案已经得到解答。

当您用 audio players and use flutter_tts 播放声音来说词时,flutter_tts 在 iOS

上无法正常工作

因此,只有一个包有效,但一旦同时使用两个包,tts 会在一段时间后停止工作。有时会持续更长时间,但有时会立即停止。

In reality ,this is due to a conflict on the iOS side.

假设它适用于 Android,这意味着您的代码应该没有问题。

必须找到另一种选择。

今天我解决了这个问题。我使用的是来自 URL 的音频,我使用的是这条线路

  var res = await audioPlayer.play(url, isLocal: true);

我必须在我的代码中使用下面这行

  var res = await audioPlayer.play(url, isLocal: false);

isLocal代表你的文件是否存储在本地。如果文件以 URL 的形式远程存储,则设置为 isLocal:false.

希望它能解决您的问题。

在使用 IOS 时使用 play() 方法而不是 playBytes()。整数结果=0; if(Platform.isIOS){ result = await player.play("音频url",isLocal: false); }