🎧

Expo Audioで音を鳴らす

2025/01/30に公開

はじめに

  • アプリの中で、「音を鳴らしたい」って思うことありますよね?
  • 実際に、Expoアプリの中で音を鳴らせるようにするまでやってみました🍵
  • 今回は「Expo Audio」と呼ばれる、expo-avをベースにした音声再生・録音ライブラリを使います。

まとめ

  • Expo Audio(expo-av)を使えば、簡単に音声の再生・録音を実装できる
  • 近い将来、expo-audioとして改良版がリリース予定。

Expo AVとは?

https://docs.expo.dev/versions/latest/sdk/audio-av/

  • 概要
    • Expo Audioは、expo-avを使って音声再生や録音を簡単に実現できるライブラリ。
    • expo-audioとして改良版がリリース予定。現時点ではexpo-avが安定版の位置づけ。
  • 機能
    • 音声再生(ローカルファイルやストリーミング対応)
    • 録音(マイク入力のキャプチャ)
  • 使える場面
    • 音楽再生アプリ
    • 学習用アプリ(発音録音など)
    • ボイスメモアプリ
  • 注意点
    • tvOS(Apple TV)では録音APIは利用できない。

セットアップ

  • 前提条件:プロジェクトにexpo がインストールされていること

  • パッケージのインストール

    npx expo install expo-audio
    
  • mp3の型ファイルを作成しておく

    • TypeScriptを利用する場合、.mp3ファイルをインポートするときの型定義が必要。
    • 以下のいずれかを*.d.tsファイルで用意しておく
      1. declare module "*.mp3";
        • インポート時の型が any となり、型安全性は低いが簡単。
      2. declare module "*.mp3" { const value: string; export default value; }
        • インポートした値が string型と認識されるため、ある程度型安全。
  • 音声ファイルの配置

    • assets/sounds のようなディレクトリを作成し、そこに .mp3 ファイルを保存しておく。

使い方

  • 以下は音を鳴らすだけの最小構成例です。
  1. カスタムフック useAudio の作成例
import { useEffect, useState } from "react";
import { Audio, type AVPlaybackSource } from "expo-av";

type Props = {
  audioSource: string;
};

export const useAudio = ({ audioSource }: Props) => {
  const [sound, setSound] = useState<Audio.Sound | null>(null);

  useEffect(() => {
    // コンポーネントがアンマウントされる際にサウンドをクリーンアップ
    return () => {
      if (sound) {
        void sound.unloadAsync();
      }
    };
  }, [sound]);

  const playSound = async () => {
    const { sound } = await Audio.Sound.createAsync(
      audioSource as unknown as AVPlaybackSource,
    );
    setSound(sound);
    await sound.playAsync();
  };

  return { playSound };
};
  1. 実際にコンポーネントで呼び出す
import { View, StyleSheet, Button } from 'react-native';
import audioSource from "assets/sounds/sample.mp3";
import { useAudio } from "./useAudio"; // 上記のカスタムフック

export default function App() {
  const { playSound } = useAudio({ audioSource });

  return (
    <View style={styles.container}>
      <Button title="Play Sound" onPress={playSound} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    backgroundColor: '#ecf0f1',
    padding: 10,
  },
});

おわりに

  • Expo Audio(expo-av)を用いた簡単な音声再生ができるようになりました。
  • 機会があれば、一時停止、無限ループや録音機能なども試してみたいです。

Discussion