質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

3回答

806閲覧

Javascript 音が再生されるタイマーを作成中、実装が上手にいきません

hanamizuki_mapl

総合スコア18

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2020/01/27 17:29

編集2020/01/28 12:39

前提・実現したいこと

はじめまして。

私は今JavascriptとHTML5の組み合わせで5分置きに音が再生されるウェブアプリを作成しています。

JavascriptはほぼサイトやjQueryを少し囓って実装している程度で初心者でございます。

発生している問題・エラーメッセージ

関数func1でaudioタグを生成したあと、テキストボックスに入力したMP3URLを呼び出し再生はできるようになりました。

私はjSの知識が浅く、無理やりINNERHTMLでAUDIOタグを生成し、ローカルストレージに保存したmp3urlを呼び込み、再生する事にしました。

但し、再生される時と再生されない時が発生し、様々なサイトを見て試行錯誤しましたが手に負えなくなりました。

誠に勝手なのですが、Javascriptにお詳しい方がいらっしゃいましたらこの問題の解決方法を教えていただけないでしょうか。

よろしくお願いします。

###main.jsファイルについて
func1関数は実行するとindex.html内にaudioタグを生成し、音ファイルのURL入力欄の値を取得し、再生するようにしています。

但しこの実装方法は間違っていると自分でも認識しています。

リアルタイムを取得し、if文によりスクリプトを実行するようにしています。
ローカルストレージは設定や、音のURLを保存するようにしています。

該当のソースコード

html

1<html lang="ja"> 2<head> 3<meta charset="utf-8"/> 4<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> 5<script type="text/javascript" src="main.js"></script> 6 7</head> 8<body> 9現在時刻は<div id="coltime" style="color:#000;"></div>分です 10<form name="form1" style=""> 11<label><input type="checkbox" id="checkbox2" value="0" onchange="chkboxchk(this.value)">チェックボックス1</label><br> 12<label><input type="checkbox" id="checkbox1" value="0" onchange="chkboxchk(this.value)">チェックボックス2</label><br> 13<label><input type="checkbox" id="checkbox3" value="0" onchange="chkboxchk(this.value)">チェックボックス3</label><br> 14</form> 15<form name="form2" style="font-weight: bold;display:none;"> 16<label><input type="checkbox" id="checkbox4" value="0" onchange="chkboxchk(this.value)">チェックボックス4</label><br> 17</form> 18<input type="text" id="sound1"> 19<input type="button" value="ローカルストレージ保存" onclick="lclstrg.save();"> 20<div id="output_message"></div> 21MP3URLをここに入力<br> 22<!--サンプルURL https://soundeffect-lab.info/sound/button/mp3/decision1.mp3--> 23 <form id="form1" action="#"> 24 <input type="button" onclick="func1()" value="func1()実行"> 25 </form> 26 27</body> 28<script type="text/javascript" language="JavaScript"> 29setInterval(ms2bgcolGreeting, 1000); 30ms2bgcolGreeting(); 31</script> 32</html> 33

js

1コードが長く投稿できないため外部ファイルです 2https://d.kuku.lu/38042174ec

追記します 【2020/01/28 21:38】
本来はページを開いた時にローカルストレージに保存した値=sound1を自動で取得し、if文をトリガーとして再生されるようにしたいと思ってました。
リアルタイムで分が変わったときにfunc1()を実行。

最初に記載したソースコードでは一度func1()を実行しないとif文によるトリガーで再生されないことが理解できました。
その後、ソースコードを短縮し最小規模でローカルストレージに保存した値を取得するページを作成してみたのですが取得ができてませんでした。

検証用のページがこちらになります。 https://maplestory2.online/tera/index.html

ページを開いたときにローカルストレージに保存したsound1の値を取得し、audioタグ、sourceタグを生成し、if文で分が変わった時に再生できるように実装することは可能なのでしょうか。

重ねて質問しますがよろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

当方でもテストコードを書いてみましたが、残念ながらユーザーのアクションなしにAudioを再生することはできませんでした。
外部ページを開くのがなんとなく嫌で元のコードを見ていませんので、あまり参考にならないかもしれませんが、せっかくなので記録として残しておきたいと思います。

ライブラリとして base64-binary.js を読み込む必要があります。

html

1<!doctype html> 2<html> 3<head><meta charset="UTF-8"><title>Web Audio API + Local Storage</title></head> 4<body> 5<label>Source URL: <input type="url" id="url"></input></label> 6<button type="button" id="load">Laod Audio File</button> 7</body> 8</html>

js

1class IntervalPlayer { 2 constructor() { 3 this.audioCtx = new (window.AudioContext || window.webkitAudioContext)(); 4 if(!this.audioCtx) { 5 throw new Error("This browser don't support the Web Audio API"); 6 } 7 8 this.intervalId = null; 9 this.audioData = null; 10 this.bufferSource = null; 11 this.isPlaying = false; 12 13 // consts 14 this.storageKey = 'encodedByAudio'; 15 this.intervals = 5 * 60 * 1000; 16 17 // DEBUG: Set 5 seconds for debugging 18 this.intervals = 5 * 1000; 19 } 20 21 setLoopPlayerIfLocalStorageHaveAudio() { 22 const base64 = window.localStorage.getItem(this.storageKey); 23 if(!base64) return; 24 25 this.audioCtx.decodeAudioData(Base64Binary.decodeArrayBuffer(base64), audioData => { 26 this.audioData = audioData; 27 if(!!this.audioData) this.setLoopPlayer(); 28 }); 29 } 30 31 setLoopPlayer() { 32 if(!!this.intervalId) this.clearLoopPlayer(); 33 this.intervalId = window.setInterval(() => { 34 this.stopAudioIfPlaying(); 35 this.playAudio(); 36 }, this.intervals); 37 } 38 39 clearLoopPlayer() { 40 if(!this.intervalId) { 41 console.warn('Already loop disabled.'); 42 return; 43 } 44 window.clearInterval(this.intervalId); 45 this.stopAudioIfPlaying(); 46 this.intervalId = null; 47 } 48 49 playAudio() { 50 this.bufferSource = this.audioCtx.createBufferSource(); 51 this.bufferSource.buffer = this.audioData; 52 this.bufferSource.connect(this.audioCtx.destination); 53 this.bufferSource.start(); 54 this.isPlaying = true; 55 } 56 57 stopAudioIfPlaying() { 58 if(!this.isPlaying) return; 59 this.bufferSource.stop(); 60 this.bufferSource.disconnect(); 61 this.isPlaying = false; 62 } 63 64 getAudioSourceWithUrl(url) { 65 fetch(url).then(res => res.blob().then(blob => { 66 const reader = new FileReader(); 67 reader.addEventListener('loadend', () => { 68 const base64 = reader.result.toString(); 69 window.localStorage.setItem(this.storageKey, base64); 70 this.setLoopPlayerIfLocalStorageHaveAudio(); 71 }); 72 reader.readAsDataURL(blob); 73 })); 74 } 75} 76 77window.document.body.addEventListener('click', initIntervalPlayer); 78 79function initIntervalPlayer() { 80 window.intervalPlayer = new IntervalPlayer(); 81 window.intervalPlayer.setLoopPlayerIfLocalStorageHaveAudio(); 82 window.document.body.removeEventListener('click', initIntervalPlayer); 83} 84 85document.getElementById('load').addEventListener('click', () => { 86 const url = document.getElementById('url').value; 87 window.intervalPlayer.getAudioSourceWithUrl(url); 88});

投稿2020/01/29 10:05

thyda.eiqau

総合スコア2982

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

沢山の回答ありがとうございます。
URLを取得できない原因が分かりました。
alertを実行する前にローカルストレージをロードしていない事が原因でした。
検証用ページ https://maplestory2.online/tera/index.html
-----lclstrg.load();がローカルストレージロードです-----
lclstrg.load();
var shutoku = document.getElementById("sound1").value;
SOURCE.src = shutoku;
alert("取得したURLは「"+shutoku+"」です");


音がならない時、なるときがある件について

ページを開いた時に自動でAudioが再生されないことがわかりました。
開発者モードのconsoleを見てみると Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first. と表示され、Chromeの自動再生をブロックしているエラーコードが発生していました。
ブラウザ固有の自動再生のブロックはページをクリックしたり何らかの操作をしないと解除されないようです。
ページをクリックするとif文で指定した時刻に音声がなりますが、本来考えていた実装方法とは違い試行錯誤が必要だと感じました。

投稿2020/01/29 08:54

hanamizuki_mapl

総合スコア18

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

とりあえずJavascirptソースは長いため音楽再生の部分だけ修正してみました。
setAttributeメソッドを使うことで任意のプロパティに値を渡せます。
今回は一曲しか設定してないようなのでaudioタグに設定しています。

後、時間間隔での実行はsetIntervalのみでいけます。
渡す時間の単位がミリ秒なので5分なら300000を渡します。
ただIntervalを解除する時がsetIntervalメソッドのオブジェクトそのものを
clearIntervalに渡さないといけない点が少し厄介ですね。
今回はそれを使って繰り返しを停止させる処理も実装しました。

HTML

1<html lang="ja"> 2<head> 3<meta charset="utf-8"/> 4<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> 5<script type="text/javascript" src="main.js"></script> 6 7</head> 8<body> 9現在時刻は<div id="coltime" style="color:#000;"></div>分です 10<form name="form1"> 11<label><input type="checkbox" id="checkbox2" value="0" onchange="chkboxchk(this.value)">チェックボックス1</label><br> 12<label><input type="checkbox" id="checkbox1" value="0" onchange="chkboxchk(this.value)">チェックボックス2</label><br> 13<label><input type="checkbox" id="checkbox3" value="0" onchange="chkboxchk(this.value)">チェックボックス3</label><br> 14</form> 15<form name="form2" style="font-weight: bold;display:none;"> 16<label><input type="checkbox" id="checkbox4" value="0" onchange="chkboxchk(this.value)">チェックボックス4</label><br> 17</form> 18<input type="text" id="sound1" value=""> 19<input type="button" value="ローカルストレージ保存" onclick="lclstrg.save();"> 20<audio id="Sound"> 21 <p>お使いの環境では再生できません。</p> 22</audio> 23MP3URLをここに入力<br> 24<!--サンプルURL https://soundeffect-lab.info/sound/button/mp3/decision1.mp3--> 25<input type="button" onclick="setSound()" value="音楽再生"> 26<input type="button" onclick="soundStop()" value="音楽停止"> 27 28</body> 29</html>

javascript

1// Intervalオブジェクト 2var intervalObj; 3var soundInterval = function(){ 4 // ミリ秒なので5分なら5*60*1000=300000 5 intervalObj = setInterval(soundPlay, 300000); 6}; 7 8function setSound() { 9 var soundValue = document.getElementById("sound1").value; 10 document.getElementById("Sound").setAttribute("src", soundValue); 11 soundPlay(); 12 // Intervalを実行する 13 soundInterval(); 14} 15 16function soundPlay() { 17 document.getElementById("Sound").play(); 18} 19 20function soundStop() { 21 // Intervalをクリアする 22 clearInterval(intervalObj); 23}

投稿2020/01/28 11:32

yureighost

総合スコア2183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hanamizuki_mapl

2020/01/28 12:20

回答ありがとうございます。 本来はページを開いた時にローカルストレージに保存した値=sound1を自動で取得し、if文をトリガーとして再生されるようにしたいと思ってました。 リアルタイムで分が変わったときにfunc1()を実行。 最初に記載したソースコードでは一度func1()を実行しないとif文によるトリガーで再生されないことが理解できました。 その後、ソースコードを短縮し最小規模でローカルストレージに保存した値を取得するページを作成してみたのですが取得ができてませんでした。 検証用のページがこちらになります。 https://maplestory2.online/tera/index.html ページを開いたときにローカルストレージに保存したsound1の値を取得し、audioタグ、sourceタグを生成し、if文で分が変わった時に再生できるように実装することは可能なのでしょうか。 重ねて質問しますがよろしくお願い致します。
yureighost

2020/01/28 12:58

時間経過自体は同じようにsetIntervalでその都度時間取得すれば良さそうなのでいけると思いますが、 よくわからないのがローカルストレージのところですね。 ファイルアップロード的な物を想定しているのでしたら、 サーバサイド実装はどうしても必要で、 クライアントのJavascriptのみの実現は無理だと思われます。
kyoya0819

2020/01/28 13:20

Firebase Storageを使えばJavaScriptだけで可能です。
thyda.eiqau

2020/01/29 01:06 編集

やったことないですが、base64にすればローカルストレージに保持できるのでは?という気がします (base64にしなくても保持できるのかもしれませんが)
yureighost

2020/01/29 01:49

失礼しました。 ローカルストレージの機能を私が把握してなかったため、 おかしなコメントになってしまいましたが、調べて理解はできました。 ローカルストレージは文字列形式での保存となるのでthyda.eiqauさんが言っている通り、 base64等で音楽データを文字列に変換する処理が必要そうですね。
hanamizuki_mapl

2020/01/29 08:52 編集

沢山の回答ありがとうございます。 URLを取得できない原因が分かりました。 alertを実行する前にローカルストレージをロードしていない事が原因でした。 検証用ページ https://maplestory2.online/tera/index.html -----lclstrg.load();がローカルストレージロードです----- lclstrg.load(); var shutoku = document.getElementById("sound1").value; SOURCE.src = shutoku; alert("取得したURLは「"+shutoku+"」です"); ----- ----- 音がならない時、なるときがある件について ページを開いた時に自動でAudioが再生されないことがわかりました。 開発者モードのconsoleを見てみると Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first. と表示され、Chromeの自動再生をブロックしているエラーコードが発生していました。 ブラウザ固有の自動再生のブロックはページをクリックしたり何らかの操作をしないと解除されないようです。 ページをクリックするとif文で指定した時刻に音声がなりますが、本来考えていた実装方法とは違い試行錯誤が必要だと感じました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問