90515


### 解決したいこと

rails側に保存した音声ファイルをReact側のwavesurferで使用したいです。

### 環境

・dockerを使用して、バックエンド側（RoR）とフロントエンド側{React TypeScript
*(wavesurferなどの一部はJavaScript）}に分けて開発を行っています。OSはWindowsですが、wsl2のUbuntu20.04で開発を行っています。  
・Rails側では、CarrierwaveとActive_storageを試してみましたが、どちらもrails側に保存した音声ファイルをReact側のwavesurferで使用した時のみ上手くWevesurferで描画できませんでした。現在はActive_storageを使用しています。

### 発生している問題

エラーは発生しないのですが、rails側に保存した音声ファイルをReact側のwavesurferで使用した時にのみWevesurferの波形が描写されません。

## １ その場でアップロードしたファイルをwevesurferで使う場合

こちらのサイトを参考にさせて頂き、そのまま使用しています。

<https://www.wizard-notes.com/entry/javascript/react-wavesurfer-js>

[code]

    export function WSF() {
    
    const waveformRef = useRef(null);
       var context = null;
       console.log(waveformRef)
     
       const handlePlayPause = () => {
         waveformRef.current.playPause();
         console.log("handlePlayPause")
       }
       
       const handleChangeFile = (e) => {
         if (context == null) {
             window.AudioContext = window.AudioContext || window.webkitAudioContext;
             context = new AudioContext();
    
             waveformRef.current = WaveSurfer.create({
                container: waveformRef.current,
                audioContext: context,
             });
            console.log(waveformRef);
         }
    
         const file = e.target.files[0]
         console.log(file)
         if (file) {
             const fileUrl = URL.createObjectURL(file)
             waveformRef.current.load(fileUrl); 
             console.log(fileUrl)
         }
       }
           
       return (
         <div>
           <div ref={waveformRef}></div>
           <input type="file" accept="audio/*" onChange={(e) => handleChangeFile(e)} />
           <button onClick={handlePlayPause}>Play/Pause</button>
         </div>
       );
    }
    
[/code]

この場合、ファイルを選択すると、wevesurferで正常に波形が描写されます。

### 1` このコードを参考にしてローカル（Rails側）のファイルを使用できるか？

以下のコードを全て試してみましたが、どれもエラーは出ないものの、波形が描写されませんでした。また、useRefを使用する都合上、ロードボタンをクリックしてから波形が描写されるという仕様になっています。また、同じ部分は省略しました。

### そのままパラメータを渡した場合

[code]

    // そのままパラメータを渡した場合。p_fileが取得した音声ファイルのパラメータ
    export function WSF_stock(p_file) {
      const waveformRef = useRef(null);
      var context = null;
    
      const handlePlayPause = () => {
        waveformRef.current.playPause();
        console.log("handlePlayPause")
      }
      
      const handleChangeFile = (e) => {
    
        if (context == null) {
          // context = new AudioContext();
            window.AudioContext = window.AudioContext || window.webkitAudioContext;
            context = new AudioContext();
    
            waveformRef.current = WaveSurfer.create({
               container: waveformRef.current,
               audioContext: context,
            });
    // ここから
            console.log(waveformRef)
            console.log(p_file)
                waveformRef.current.load(p_file); 
    // ここまでを入れ替えていきます
      
        }
      }
      return (
        <div>
          <div ref={waveformRef}></div>
          <button onClick={(e) => handleChangeFile(e)}>ロード</button>
          <button onClick={handlePlayPause}>Play/Pause</button>
        </div>
      );
      }
    
    // console
    {file: '/rails/active_storage/blobs/redirect/eyJfcmFpbHMiO…%E3%82%B9%E3%83%AC%E3%83%8A%E3%82%B0%E3%82%B5.mp3'}
    file: "/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBEUT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--b196a9a15bdc6cd3711c34dd46ca1a27962720a3/%E3%83%AF%E3%82%B9%E3%83%AC%E3%83%8A%E3%82%B0%E3%82%B5.mp3"
    [[Prototype]]: Object
    このようにデータは渡っている
    
    
[/code]

### 一旦ファイルオブジェクトを生成してからそれをURLにしてロード

[code]

    const new_file = new File([p_file], "保存された音声",{type: "audio/mpeg"})
    const NewFile = URL.createObjectURL(new_file)
    waveformRef.current.load(NewFile); 
    
    // console
    
    {current: WaveSurfer}current: WaveSurfer {_disabledEventEmissions: Array(0), handlers: null, defaultParams: {…}, backends: {…}, util: {…}, …}[[Prototype]]: Object
    wavesurfer.jsx:69 {file: '/rails/active_storage/blobs/redirect/eyJfcmFpbHMiO…%E3%82%B9%E3%83%AC%E3%83%8A%E3%82%B0%E3%82%B5.mp3'}file: "/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBEQT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--
    ad9777f976b16c2879d73e76e7d749f1ba2c1293/%E3%83%AF%E3%82%B9%E3%83%AC%E3%83%8A%E3%82%B0%E3%82%B5.mp3"[[Prototype]]: Object
    wavesurfer.jsx:85
    
[/code]

### blobにして渡してみる

[code]

    const blob = new Blob([p_file], {type: "audio/mpeg"})
    const NewFile = URL.createObjectURL(blob)
    console.log(NewFile)
    waveformRef.current.load(NewFile); 
    
[/code]

### ファイルにしてみる

[code]

    const Newfile = new File([p_file], "保存された音声",{type: "audio/mpeg"})
    waveformRef.current.load(NewFile); 
    
[/code]

###

### ロードの仕方を変える

[code]

    waveformRef.current.load(); => waveformRef.current.loadBlob(); 
    
[/code]

### 自分の考察

・このコードの場合、ファイルをそのまま直接アップロードした場合にしかwevesurferの描写を受け付けないという結論に至りました。ファイルを直接渡すと、

[code]

    File {name: 'Night_Sea.mp3', lastModified: 1647685053601, lastModifiedDate: Sat Mar 19 2022 19:17:33 GMT+0900 (日本標準時), webkitRelativePath: '', size: 947012, …}lastModified: 1647685053601lastModifiedDate: Sat Mar 19 2022 19:17:33 GMT+0900 (日本標準時) {}name: "Night_Sea.mp3"size: 947012type: "audio/mpeg"webkitRelativePath: ""[[Prototype]]: File
    wavesurfer.jsx:35 blob:http://localhost:4000/8d6613ff-4084-4952-a218-6c97701ddb0c
    
[/code]

このように描写されます。一応これと同じように、一旦保存しているデータをファイルにして入れてみましたがなぜか上手く描写されませんでした。  
また、ここで詰まってしまったため、新しい方法を模索していると、

<https://www.npmjs.com/package/wavesurfer-react#wavesurfer>

このWevesurferをReactで使えるようにするJSライブラリーを見つけたので、使用してみることにしました。

## 2 ローカル（フロントエンド側）に保存した音声ファイルを再生する場合

＊このライブラリーは新しいため、参考記事が少なく、手探りで仕様を何とか把握しようとしたため、間違った認識をしているかもしれません

<https://codesandbox.io/s/wavesurfer-react-20-gqvb6>

・このライブラリーの仕様は恐らく、フロントエンド側のパブリックディレクトリにある音声ファイルのみにアクセス可能だと思われます。  
・試しに別のディレクトリ(imgなど)を作成して音声ファイルを移動させてみたところ、相対パスが正しくても音声ファイルを読み込まないことを確認しました。  
・私の作成しているアプリの挙動としては、  
１ React側で音声ファイルなどのデータを受け取り、axiosでrails側にPostし保存。音声ファイルはActiveStrageに保存される。  
２ Getリクエストを送ってrails側からデータ取得  
３ 取得したデータを使用してwevesurferにデータを入れて波形を描写  
という挙動をして欲しいため、このライブラリーの使用を断念致しました。

また、一応ActiveStrageを使用する際に参考にしたサイトを載せておきます

<https://dev.to/jblengino510/uploading-files-in-a-react-rails-app-using-
active-storage-201c>

### その他

・一応rails側に保存した音声ファイルをReact側のwavesurferで使用する時にのみ、波形が描写されないだけで、データの受け渡しは出来ていると思われます。他にnameやanswerなどのカラムが存在しますが、上手く値を取得できていました。  
・フロントエンド側とバックエンド側に分割しないで使用した際（これと別のアプリ）は上手く描写できていました。  
・問題解決のために必要な重要な情報（ファイルなど）が抜けているかもしれません。その際はご指摘いただけますと幸いです。  
・何かしらアドバイスがあればよろしくお願いいたします。

追記  
マルチポストをしています。不快に思われたら申し訳ございません。  
<https://teratail.com/questions/92rda2btz0aef5>


CC BY-SA 4.0
2022-08-07T05:23:13.677
90418
2022-08-12T02:28:49.250
51193
question
javascript ruby-on-rails reactjs typescript
rails側に保存した音声ファイルをReact側のwavesurferで使用したい。


URLの指定の仕方が間違っていました。正しくは

[code]

    const corsAudio = new Audio(p_file.file.url);
    waveformRef.current.load(corsAudio);
    
[/code]

このように、オブジェクトをそのまま渡すのではなく、データベースから取ってきたfileオブジェクトのurlプロパティを指定して値を渡す必要があります。


CC BY-SA 4.0
2022-08-12T02:28:49.250
90515
2022-08-12T02:28:49.250
51193
90418
answer