react-native 發(fā)錄音效果

效果

屏幕錄制2021-02-01 下午5.gif

庫(kù)文件

使用到的庫(kù)有react-native-audio,teaset兩第三方庫(kù),react-native-audio用來(lái)錄音,teaset中使用Toast展示錄音效果圖。

首先

主要說(shuō)明一下這個(gè)效果,錄音功能最后說(shuō),向上代碼

export default class RecordView extends React.Component {
  static key = null;
  static show(text) {
    let showIcon;
    if (RecordView.key) RecordView.hide()
    if (text == '松開(kāi)手指取消發(fā)送') {
      showIcon = (<Image source={icCancel} style={{ width: 100, height: 100 }} />)
    } else {
      showIcon = (
        <Image source={icMic} style={{ width: 100, height: 100 }} />
      );
    }

    RecordView.key = Toast.show({
      text: (
        <Text style={{ fontSize: 13, color: 'white' }}>
          {text}
        </Text>
      ),
      icon: showIcon,
      position: 'center',
      duration: 1000000,
    });
  }
  static hide() {
    if (!RecordView.key) return;
    Toast.hide(RecordView.key);
    RecordView.key = null;
  }
}

清晰明了,2個(gè)方法,一個(gè)顯示一個(gè)隱藏。里面包含兩張圖片icCancel和icMic, 用來(lái)展示。

其次

接下來(lái)就是如何調(diào)用這個(gè)方法來(lái), 包括什么時(shí)機(jī)調(diào)用

this.Gesture = {
      onStartShouldSetResponder: (evt) => true,
      onMoveShouldSetResponder: (evt) => true,
      onResponderGrant: (evt) => {
        // console.log(evt);
        this.setState(
          {
            isRecord: true,
            recordTitle: '手指上滑動(dòng),取消發(fā)送',
            isCancel: false,
            currentPageY: evt.nativeEvent.pageY,
          },
          () => {
            RecordToast.show(this.state.recordTitle);
            this._record();
            this.props.onScroll(false);
          },
        );
      },
      onResponderMove: (evt) => {
        // console.log(evt);
        if (evt.nativeEvent.pageY - this.state.currentPageY < -5) {
          if (
            this.state.isRecord &&
            this.state.recordTitle == '手指上滑動(dòng),取消發(fā)送'
          ) {
            this.setState(
              {
                recordTitle: '松開(kāi)手指取消發(fā)送',
                isCancel: true,
              },
              () => {
                RecordToast.show(this.state.recordTitle);
              },
            );
          }
        } else if (evt.nativeEvent.pageY - this.state.currentPageY > 5) {
          if (
            this.state.isRecord &&
            this.state.recordTitle == '松開(kāi)手指取消發(fā)送'
          ) {
            this.setState(
              {
                recordTitle: '手指上滑動(dòng),取消發(fā)送',
                isCancel: false,
              },
              () => {
                RecordToast.show(this.state.recordTitle);
              },
            );
          }
        } else {
          if (!this.state.isRecord) {
            this.setState(
              {
                isRecord: true,
                recordTitle: '手指上滑動(dòng),取消發(fā)送',
                isCancel: false,
              },
              () => {
                RecordToast.show(this.state.recordTitle);
                this._record();
                this.props.onScroll(false);
              },
            );
          }
        }
      },
      onResponderRelease: (evt) => {
        console.log('3333');
        this.setState(
          {
            isRecord: false,
          },
          () => {
            RecordToast.hide();
            this._cancel(this.state.isCancel);
            this.props.onScroll(true);
          },
        );
      },
      onResponderTerminationRequest: (evt) => false,
    };

在componentDidMount方法中,初始化手勢(shì)識(shí)別代碼,復(fù)制給觸發(fā)事件的組件,
用來(lái)展示錄音圖片和取消圖片

 <View
        {...this.Gesture}
</View>

最后

進(jìn)行錄音,引入頭文件

import {AudioRecorder, AudioUtils} from 'react-native-audio';

緊接著在componentDidMount方法中

AudioRecorder.onProgress = (data) => {
    let temp = Math.floor(data.currentTime);
    if (temp >= 60) {
      this.setState(
        {
          isRecord: false,
          recordTitle: '手指上滑動(dòng),取消發(fā)送',
        },
        () => {
          RecordToast.hide();
          Alert.alert('錄制時(shí)間不能超過(guò)60秒');
          this._cancel(false);
          this.props.onScroll(true);
        },
      );
    } else {
      this.setState({
        currentTime: temp,
      });
    }
  };
  AudioRecorder.onFinished = (data) => {
  };

進(jìn)行堅(jiān)挺錄音和結(jié)束的方法
錄音開(kāi)始錄音

_record = async () => {
    if(CommonUtils.ios) {
      this.audioPath =
      AudioUtils.CachesDirectoryPath + `${new Date().getTime()}.aac`;
    } else {
      this.audioPath = AudioUtils.DocumentDirectoryPath + `${new Date().getTime()}.aac`;
    }
    this.prepareRecordingPath(this.audioPath);
    try {
      const filePath = await AudioRecorder.startRecording();
      return filePath;
    } catch (error) {
      console.log(error);
    }
  };
 prepareRecordingPath = (audioPath) => {
    AudioRecorder.prepareRecordingAtPath(audioPath, {
      SampleRate: 22050,
      Channels: 1,
      AudioQuality: 'Low',
      AudioEncoding: 'aac',
      OutputFormat: 'aac_adts',
    });
  };

這個(gè)地方需要注意一下,因?yàn)榇嬖诼窂降膯?wèn)題, AudioUtils.CachesDirectoryPath是iOS的緩存路徑,在真機(jī)和模擬器上都可以找到,如果遇到無(wú)法錄音的情況,看下log大部分都是無(wú)法創(chuàng)建datafile之類(lèi)的,說(shuō)明路徑不對(duì)。
如果遇到android上傳不了文件的問(wèn)題,注意看下log和路徑。一般都是類(lèi)似這類(lèi)問(wèn)題
停止錄音和取消錄音

_cancel = (canceled) => {
    this._stop();
    if (canceled) return;
    if (this.state.currentTime < 1) {
      Alert.alert('錄制時(shí)間太短了');
      setTimeout(() => {
        RecordToast.hide();
      }, 300);
      return;
    }
    this.setState({currentTime: null});
    setTimeout(() => {
      // 上傳音頻文件,操作
    }, 500);
  };
  _stop = async () => {
    try {
      const filePath = await AudioRecorder.stopRecording();
      return filePath;
    } catch (error) {}
  };

到此大功告成。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容