2019/06/03
こんにちは。令和元年のGW10連休いかがお過ごしでしたしょうか?
私が所属する会社では「10連休だし何かサービスを作ろうぜ!」ということで
任意の仲間同士でGW中に1人1サービスを作るGWハッカソンを開催しました。大学のサークルみたいですね。
GWハッカソンのまとめ記事もありますので、こちらも読んでいただけたら嬉しいです
→ https://praha-inc.hatenablog.com/entry/2019/05/15/202420
HEISEI REVERSE PLAYER
https://heisei-reverse-player.kukan-tech.com/
平成の名曲を逆再生でイントロドンするWebアプリです。
この記事では「HEISEI REVERSE PLAYER」の開発経緯とその技術について共有します。
動機は単純な理由でした。
個人的な話ですが、私個人の開発モチベーションの源泉が「人に使ってもらうこと」なので
多くの人が使えるであろう「ブラウザで動くもの」 = 「Web」 にこだわりました。
あとは弊社でNuxt.jsを採用しているので爆速開発が期待できました。
Webで音声を再生する方法について紹介します。
お馴染みののHTML5!
以下のようなコードで再生できます。
<audio src="sample/sample.mp3">
通常の音声再生はこれでいいのですが、今回やりたいことは「逆再生」です。
Web Audio APIを使えば逆再生なんてお手のものなんです。自由にエフェクトをかけられるようですね。
JavaScriptを使ってブラウザ上で音声の加工ができるんですよ!すごい!
とは言ったものの、意外とつらいんですこれが。
Chromeでは再生できるけれども、Safariでは再生できないなんてことが普通に起きるんです。
IE?なにそれ美味しいのって感じですね。IEではデバッグしていません。
Web Audio APIを利用した実装でハマったポイントや得た知見紹介していきます。
そもそもブラウザで提供しているWeb Audio APIのクラスが違うので、APIを利用する場合以下のように記述する必要があります。
window.AudioContext = window.AudioContext || window.webkitAudioContext
webkitAudioContext
がSafariのAudio APIでした。
Safariで Web Audio APIの async await構文が対応していませんでした。 then, catchを使う必要があります。
※ 後述したコードにコメント書いていますのでご確認ください。
Safariのポリシーで音声を再生するにはユーザのアクションをトリガーする必要があるとのことです。
なので音声を再生する場合、ボタンを押下した時にWeb Audio APIを再生する関数を実行する必要があります。
今回はボタンを押下したタイミングで音声を再生するため問題ありませんでした。
どうしても自動再生がやりたい人はこちらを参照してください。
Web Audio APIの闇
window.AudioContext = window.AudioContext || window.webkitAudioContext
const context = new AudioContext()
export const getAudioSourceWithPlay = (path, isReverse) => {
const source = context.createBufferSource()
// fetch APIで音声ファイルを取得
fetch(path)
.then(response => response.arrayBuffer())
.then(arrayBuffer => {
// 音声ファイルをデコード
// SafariのdecodeAudioDataがpromise構文に対応していない
// SafariではSuccess callbackが後から呼ばれることがあるため、source.start(0)もここで呼び出す必要がある
context.decodeAudioData(arrayBuffer, function(buf) {
// 逆再生
if (isReverse) {
Array.prototype.reverse.call(buf.getChannelData(0)) // left
Array.prototype.reverse.call(buf.getChannelData(1)) // right
}
source.buffer = buf
source.loop = false
source.connect(context.destination)
source.start(0)
})
})
return source
}
開発課題についてまとめておきます。
これは音声取得・再生のトリガーをボタン押下時にまとめてしまったため3Gなどの低速回線だとUX悪いです。
事前に取得して圧縮するなどの方法が考えられそうです。
Vuetifyを使いましょう。
開発期間は3日ぐらいでした。
今回は、iTunes Search APIとWeb Audio APIを初めて利用したので、その仕様の調査に費やす時間が長かったかなと。
手を動かした時間は1.5日ぐらいだったと思います。
HEISEI REVERSE PLAYERでした。
https://heisei-reverse-player.kukan-tech.com/
Happy Coding!