前提・実現したいこと
Ruby on rails 6 にVue.jsを導入し、音声録音を用いたサイトを作成しております。SPAでトップページで完結させたいと考えているのですが、実装方法が分からず恐れ入りますがご教示いただければ幸いです。コントローラー側でcreateアクションで受け取ったWeb Apiのレスポンスをtopアクションに渡すの処理が分からない状況です。
下記が実装したい流れです。(③が分からない状況です)
①トップページでWeb Audio APIを用いて音声を録音
②音声データをrailsのコントローラーに渡し、コントローラー内でWeb Apiに音声データをとともにリクエストを投げてレスポンスを受け取る。
③画面書き換え後のトップページにレスポンスを渡して結果表示
該当のソースコード
#static/pages/top.html mounted() { // マイクにアクセス navigator.mediaDevices.getUserMedia({ audio: true }) .then(stream => { let audioBlob; this.recorder = new MediaRecorder(stream); this.recorder.addEventListener('dataavailable', e => { this.audioData.push(e.data); this.audioExtension = this.getExtension(e.data.type); }); //ボタンを押した際に音声録音を開始し、音声データをRailsのコントローラー(createアクション)に音声データ渡す this.recorder.addEventListener('stop', () => { audioBlob = new Blob(this.audioData); console.log(audioBlob); formData = new FormData(); formData.append("audio", audioBlob); console.log(formData); $.ajax({ url: '/static_pages', //createアクションに渡す type: 'POST', contentType: false, processData: false, data: formData }); this.status = 'finishRecording'; }); //ボタンを押して画面書き換えをし、コントローラーで処理されたレスポンスを取得する document.getElementById("btn").addEventListener('click', () => { const result = gon.result;
#static_pages_controller.rb #createアクションのレスポンスを受け取りトップページへ(gem gonを使用し、Javascriptに渡す) def top gon.result = @result end #トップページから受け取った音声データを元にWeb Apiにリクエストを投げてレスポンス取得 def create @audio = params[:audio] require 'uri' require 'net/http' require 'openssl' url = URI(Settings.speaker_identification.url) http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Content-Type"] = 'audio/x-pcm;bit=16;rate=16000;channels=1' request["Ocp-Apim-Subscription-Key"] = Settings.speaker_identification.subscription_key file = File.read(@audio) request.body = file response = http.request(request) @result = response.read_body end
試したこと
ソースコードのControllerのように現在は実装していますが、これだと上手くデータを渡せずgon.result=nullになってしまいます。createアクションでrender "top"やredirect_to top_pathを試しましたがやはり上手くいきません。コールバック(after actionなど?)を使えば上手くいくのかとも思ったのですが、どうも違うような気がしました。
あなたの回答
tips
プレビュー