16
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

アイエンターAdvent Calendar 2020

Day 7

Reactでブラウザから音声を録音してFirebaseにアップロードしてみた(iOS未対応)

Last updated at Posted at 2020-12-06

経緯

最近は音声を投稿するSNSが増えてきているなぁと感じてきており、私が知っている限りでも10個は直ぐに思い出せます。
そこで、いつか音声サービスを作ってみたくなるかもしれないので、興味本位で調べてみました。

動作確認

WindowsのChrome

開発情報

  • react
  • firebase
  • react-audio-player

デモ動画

YouTubeで確認できます。
https://youtu.be/zHmhcu2CANs

コード

App.js
import React, { useEffect, useState, useRef } from "react";
import firebase from "firebase";
import ReactAudioPlayer from "react-audio-player";

// configは、自分のfirebaseの設定を指定してください。
const config = {
  apiKey: "",
  authDomain: "",
  databaseURL: "",
  storageBucket: "",
};

const App = () => {
  const [file, setFile] = useState([]);
  const [audioState, setAudioState] = useState(true);
  const audioRef = useRef();

  useEffect(() => {
    if (firebase.apps.length === 0) {
      firebase.initializeApp(config);
    }
    // マイクへのアクセス権を取得
    navigator.getUserMedia =
      navigator.getUserMedia || navigator.webkitGetUserMedia;
    //audioのみtrue
    navigator.getUserMedia(
      {
        audio: true,
        video: false,
      },
      handleSuccess,
      hancleError
    );
  }, []);

  const handleSuccess = (stream) => {
    // レコーディングのインスタンスを作成
    audioRef.current = new MediaRecorder(stream, {
      mimeType: "video/webm;codecs=vp9",
    });
    // 音声データを貯める場所
    var chunks = [];
    // 録音が終わった後のデータをまとめる
    audioRef.current.addEventListener("dataavailable", (ele) => {
      if (ele.data.size > 0) {
        chunks.push(ele.data);
      }
      // 音声データをセット
      setFile(chunks);
    });
    // 録音を開始したら状態を変える
    audioRef.current.addEventListener("start", () => setAudioState(false));
    // 録音がストップしたらchunkを空にして、録音状態を更新
    audioRef.current.addEventListener("stop", () => {
      setAudioState(true);
      chunks = [];
    });
  };
  // 録音開始
  const handleStart = () => {
    audioRef.current.start();
  };

  // 録音停止
  const handleStop = () => {
    audioRef.current.stop();
  };
  // firebaseに音声ファイルを送信
  const handleSubmit = () => {
    // firebaseのrefを作成
    var storageRef = firebase.storage().ref();
    var metadata = {
      contentType: "audio/mp3",
    };
    // ファイル名を付けてBlobからファイルを作成して送信
    var mountainsRef = storageRef.child(new Date() + "test.mp3");
    mountainsRef.put(new Blob(file), metadata).then(function () {
      console.log("アップロード完了!");
    });
  };
  const handleRemove = () => {
    setAudioState(true);
    setFile([]);
  };

  const hancleError = () => {
    alert("エラーです。");
  };

  return (
    <div>
      <button onClick={handleStart}>録音</button>
      <button onClick={handleStop} disabled={audioState}>
        ストップ
      </button>
      <button onClick={handleSubmit} disabled={file.length === 0}>
        送信
      </button>
      <button onClick={handleRemove}>削除</button>
      <ReactAudioPlayer src={URL.createObjectURL(new Blob(file))} controls />
    </div>
  );
};

export default App;

所感

ほぼ参考サイトのコピペですが、それをReactで実装してみました。
Webで音声を録音することも案外できるものだなぁと感じました。
また、音声の再生には「react-audio-player」というライブラリが直感的に使えて助かりました。
音声を録音と変換が簡単にできるreactのライブラリがあればよかったのですが...

また、iOSのブラウザではWeb Audio APIを使用する必要があるみたいで、この実装だと動きません。
実装し終えてから気づきました。。。

次はiOSに対応するバージョンと、ReactNativeでの音声の録音と保存にも挑戦してみようと思います。

最後に

※発言は個人の見解で所属組織とは無関係です

参考にした記事

16
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?