zmxv / react-native-sound

React Native module for playing sound clips
MIT License
2.79k stars 748 forks source link

我用 使用环信接收语音消息 用react native fs 下载 后 无法播放本地文件 #519

Open loss99 opened 5 years ago

loss99 commented 5 years ago

收到的语音消息的URL url: "https://a1.easemob.com/1124180905177345/yjxm/chatfiles/210c4610-ff4c-11e8-a35e-4399f0ecd2fd"

下载 过程

const downloadDest = ${RNFS.CachesDirectoryPath}/${((Math.random() * 1000) | 0)}.mp3; const formUrl = url; const options = { fromUrl: formUrl, toFile: downloadDest, background: true, begin: (res) => { console.log('begin', res); console.log('contentLength:', res.contentLength / 1024 / 1024, 'M'); }, progress: (res) => { let pro = res.bytesWritten / res.contentLength; this.setState({ progressNum: pro, }); }, }; try { console.log('12121',options); const ret = RNFS.downloadFile(options); ret.promise.then(res => { console.log('语音下载成功success', res); console.log('文件大下载地址是 downloadDest); callback(downloadDest) }).catch(err => { console.log('err', err); callback('error') }); } catch (e) { console.log(error); }

播放 过程

this.downloadFile(this.props.item.url,response=>{ if (response=='error'){ console.warn('下载失败了,请重试'); } else { console.log('我已经下载熬好了 文件 可以播放了',response) let localSong = response; setTimeout(() => { //file://var/containers/Bundle/Application/76A725C1-78CF-4B02-8CEC-CE2013EA7077/RNProjectPlayground.app/184.mp3' console.log('我要播放的是',localSong) this.sound = new Sound(localSong, '', (error) => { if (error) { console.warn(error) } else { console.log('播放准备') this.sound.play((success) => {
if (!success) { Alert.alert('播放失败'); }else { alert('1') } }); if (!this.state.duration) { this.setState({ duration: Math.floor(this.sound.getDuration()) }); } } }); }, 100) }

YS-WEI commented 5 years ago

tri it: /var/containers/Bundle/Application/76A725C1-78CF-4B02-8CEC-CE2013EA7077/RNProjectPlayground.app/184.mp3'

Android: I is use require(), and resolveAssetSource() is return 'file:///..../xxx.mp3' In createMediaPlayer of RNSoundModule.java, has check file exist. (File file = new File(fileName);) This will convert path to 'file:/.../xxx.mp3', but this path is fail.

I read setDataSource of MediaPlayer. The setDataSource already have convert path and check exist. But, this convert path is return '/.../xxx.mp3'. This is correct. So, Maybe you can modify createMediaPlayer of RNSoundModule.java, or replace 'file://'

loss99 commented 5 years ago

@WilsWei 下载后的文件路径 ===> /var/mobile/Containers/Data/Application/56158DE8-2CB2-47C4-9C0D-752F9DE7340E/Library/Caches/900.mp3 我修改了 文件路径 但是 依然 没生效 this.sound.play 没执行 RN 0.52
iOS "react-native-sound": "^0.10.9", mac : 10.14 (18A389)

YS-WEI commented 5 years ago

@loss99 原來您是在iOS上遇到的問題, 我是在Android上遇到的, 上面所說的解法無法幫助到您, 我對iOS的檔案路徑也不太熟悉, 所以沒有辦法幫助到您

也許你可以看一下iOS Native code Debug這段程式

RCT_EXPORT_METHOD(prepare:(NSString*)fileName
                  withKey:(nonnull NSNumber*)key
                  withOptions:(NSDictionary*)options
                  withCallback:(RCTResponseSenderBlock)callback) {
  NSError* error;
  NSURL* fileNameUrl;
  AVAudioPlayer* player;

  if ([fileName hasPrefix:@"http"]) {
    fileNameUrl = [NSURL URLWithString:fileName];
    NSData* data = [NSData dataWithContentsOfURL:fileNameUrl];
    player = [[AVAudioPlayer alloc] initWithData:data error:&error];
  }
  else if ([fileName hasPrefix:@"ipod-library://"]) {
    fileNameUrl = [NSURL URLWithString:fileName];
    player = [[AVAudioPlayer alloc] initWithContentsOfURL:fileNameUrl error:&error];
  }
  else {
    fileNameUrl = [NSURL URLWithString: fileName];
    player = [[AVAudioPlayer alloc]
              initWithContentsOfURL:fileNameUrl
              error:&error];
  }

  if (player) {
    player.delegate = self;
    player.enableRate = YES;
    [player prepareToPlay];
    [[self playerPool] setObject:player forKey:key];
    callback(@[[NSNull null], @{@"duration": @(player.duration),
                                @"numberOfChannels": @(player.numberOfChannels)}]);
  } else {
    callback(@[RCTJSErrorFromNSError(error)]);
  }
}