iT邦幫忙

1

(已解決)多個按鈕控制多個wavesurfer.js聲音檔

延伸我的前幾篇問題:(已解決)使用 wavesurfer.js 顯示聲音的波形圖
我想加個幾個按鈕來控制多個聲音檔的播放與暫停,包含:快速播放、正常播放、慢速播放、暫停。
我嘗試過,如果只有控制一個聲音檔的話可以,但多個聲音檔的話,目前只能控制到最後一個聲音檔
目前程式碼大致如下(PS:在loadvoice()部分的寫法重複了很多次,請先見諒):

Javascript部分:

var btnCheck = 0;
var btnRate = 1;
document.onclick=function(){
	var obj = event.srcElement; 
	if(obj.type == "button")
	{ 
		if(obj.id == "fastPlay"){
			btnCheck = 1; //播放
			btnRate = 1.3; //快速
			loadvoice();
		}else if(obj.id == "slowPlay"){
			btnCheck = 1; //播放
			btnRate = 0.7; //慢速
			loadvoice();
		}else if(obj.id == "btnPlay"){
			btnCheck = 1; //播放
			btnRate = 1; //正常
			loadvoice();
		}else if(obj.id == "btnPause"){
			btnCheck = 2; //暫停
			loadvoice();
		}
	} 
}

function loadvoice(){
	if(btnCheck == 0 && btnRate == 1){
		for(i = 0 ; i < waveNum ; i++){
			var wavesurfer = 'wavesurfer' + i;
			wavesurfer = WaveSurfer.create({
				container: '#waveform_'+i,
				waveColor: 'violet',
				progressColor: 'purple',
				audioRate: btnRate
			});
			var voicepath = 'voice/'+voicename+'/'+voicename+'.pcm_'+i+'.wav';
			wavesurfer.load(voicepath);
		}
		wavesurfer.on('ready', function () {
			wavesurfer.play();
		});
	}else if(btnCheck == 1 && btnRate == 0.7){
		for(i = 0 ; i < waveNum ; i++){
			var wavesurfer = 'wavesurfer' + i;
			wavesurfer = WaveSurfer.create({
				container: '#waveform_'+i,
				waveColor: 'violet',
				progressColor: 'purple',
				audioRate: btnRate
			});
			var voicepath = 'voice/'+voicename+'/'+voicename+'.pcm_'+i+'.wav';
			wavesurfer.load(voicepath);
		}
		wavesurfer.on('ready', function () {
			wavesurfer.play();
		});
	}else if(btnCheck == 1 && btnRate == 1){
		for(i = 0 ; i < waveNum ; i++){
			var wavesurfer = 'wavesurfer' + i;
			wavesurfer = WaveSurfer.create({
				container: '#waveform_'+i,
				waveColor: 'violet',
				progressColor: 'purple',
				audioRate: btnRate
			});
			var voicepath = 'voice/'+voicename+'/'+voicename+'.pcm_'+i+'.wav';
			wavesurfer.load(voicepath);
		}
		wavesurfer.on('ready', function () {
			wavesurfer.play();
		});
	}else if(btnCheck == 1 && btnRate == 1.3){
		for(i = 0 ; i < waveNum ; i++){
			var wavesurfer = 'wavesurfer' + i;
			wavesurfer = WaveSurfer.create({
				container: '#waveform_'+i,
				waveColor: 'violet',
				progressColor: 'purple',
				audioRate: btnRate
			});
			var voicepath = 'voice/'+voicename+'/'+voicename+'.pcm_'+i+'.wav';
			wavesurfer.load(voicepath);
		}
		wavesurfer.on('ready', function () {
			wavesurfer.play();
		});
	}else if(btnCheck == 2){
		for(i = 0 ; i < waveNum ; i++){
			var wavesurfer = 'wavesurfer' + i;
			wavesurfer = WaveSurfer.create({
				container: '#waveform_'+i,
				waveColor: 'violet',
				progressColor: 'purple',
				audioRate: 1
			});
			var voicepath = 'voice/'+voicename+'/'+voicename+'.pcm_'+i+'.wav';
			wavesurfer.load(voicepath);
		}
	}
}

HTML部分:

<?php
for($i = 0 ; $i < 24 ; $i++){
	echo "
	<div id='waveform_$i' class='waveform' style='background-color:rgba(255, 255, 255, 0.5)'></div><br>
	<div class='btn-group' role='group'>
		<button type='button' class='btn btn-secondary' id='fastPlay' name='fastPlay_$i' onclick=submit(this)>快速播放</button>
		<button type='button' class='btn btn-secondary' id='btnPlay' name='btnPlay_$i' onclick=submit(this)>正常播放</button>
		<button type='button' class='btn btn-secondary' id='slowPlay' name='slowPlay_$i' onclick=submit(this)>慢速播放</button>
		<button type='button' class='btn btn-warning' id='btnPause' name='btnPause_$i' onclick=submit(this)>暫停</button>
	</div>
	";
}
?>

2 個回答

1
dragonH
iT邦超人 5 級 ‧ 2020-04-09 15:00:23
最佳解答

先猜

function loadvoice(){
	if(btnCheck == 0 && btnRate == 1){
		for(let i = 0 ; i < waveNum ; i++){
        ....

這樣

我後來實測一下

你的 code 現在應該連暫停都有問題吧

每個 button 都會 create 一個

看更多先前的回應...收起先前的回應...
小斑 iT邦新手 4 級 ‧ 2020-04-09 15:35:00 檢舉

是的><
(加了let還是一樣問題)

dragonH iT邦超人 5 級 ‧ 2020-04-09 16:46:50 檢舉

小斑

<html>
<script src = 'https://cdnjs.cloudflare.com/ajax/libs/wavesurfer.js/3.3.1/wavesurfer.min.js'></script>
<?php
for($i = 0 ; $i < 3 ; $i++){
	echo "
	<div id='waveform_$i' class='waveform' style='background-color:rgba(255, 255, 255, 0.5)'></div><br>
	<div class='btn-group' role='group'>
		<button type='button' class='btn btn-secondary' name='btnFastPlay' data-id = '$i'>快速播放</button>
		<button type='button' class='btn btn-secondary' name='btnPlay' data-id = '$i'>正常播放</button>
		<button type='button' class='btn btn-secondary' name='btnSlowPlay' data-id = '$i'>慢速播放</button>
		<button type='button' class='btn btn-warning' name='btnPause' data-id = '$i'>暫停</button>
	</div>
	";
}
?>
<script>
let voicename = 'demo';
const voices = Array.from({ length: 3 }).map((el, i) => {
    let wavesurfer = 'wavesurfer' + i;
			wavesurfer = WaveSurfer.create({
				container: '#waveform_'+i,
				waveColor: 'violet',
				progressColor: 'purple',
				audioRate: 1
			});
			let voicepath = 'voice/'+voicename+'/'+voicename+'.pcm_'+i+'.wav';
			wavesurfer.load(voicepath);
            return wavesurfer;
})
document.onclick=function(){
	const obj = event.srcElement; 
    console.log(obj)
	if(obj.type == "button") { 
		if(obj.name == "btnFastPlay"){
			voiceControl(obj, 'fast');
		}else if(obj.name == "btnSlowPlay"){
			voiceControl(obj, 'slow');
		}else if(obj.name == "btnPlay"){
			voiceControl(obj, 'play');
		}else if(obj.name == "btnPause"){
			voiceControl(obj, 'stop');
		}
	} 
}

const voiceControl = (voice, action) => {
    const voiceId = voice.dataset.id;
    console.log(action)
    switch (action) {
        case 'fast': {
            voices[voiceId] && voices[voiceId].setPlaybackRate(1.3);
            voices[voiceId] && voices[voiceId].play();
            break;
        }
        case 'slow': {
            voices[voiceId] && voices[voiceId].setPlaybackRate(0.7);
            voices[voiceId] && voices[voiceId].play();
            break;
        }
        case 'play': {
            voices[voiceId] && voices[voiceId].play();
            break;
        }
        case 'stop': {
            voices[voiceId] && voices[voiceId].pause();
            break;
        }
    }
};
</script>
</html>

大概改了一下

總之

一開始先把 voice 初始化

並存在某個 array(demo 而已 大量可能不會這樣做

然後

你需要知道你現在要操作的是哪一個 voice

再對他進行 play 或 stop

官方也有提供setPlaybackRate這個 function

可以讓你可以調整 rate

可能有空再補個 codepen demo

小斑 iT邦新手 4 級 ‧ 2020-04-09 18:09:32 檢舉

謝謝~
先試了一下
目前遇到如下訊息
https://ithelp.ithome.com.tw/upload/images/20200409/20106496c8BaVhy63J.jpg
晚點再來試試看

小斑 iT邦新手 4 級 ‧ 2020-04-10 15:30:26 檢舉

謝謝dragonH
測試可以達到我想要的效果~^^

dragonH iT邦超人 5 級 ‧ 2020-04-10 15:47:01 檢舉

/images/emoticon/emoticon12.gif

0
浩瀚星空
iT邦超人 1 級 ‧ 2020-04-09 15:04:12

只提示你一個重點。
id名稱不能重覆。

依照你的程式碼。其按鍵的id名是會發生重覆的情況。
雖然目前看你的寫法看起來影響不大。
但還是不要太小看javascript超級大問題。

id能不重覆就不要重覆。就算你認為你不是用他來當觸發名。

另外寫法上你也得改一下。
理論上來看。你要每一個音源都有各自的控制器。
理當來說,因該是各自控制各自才對。

不過看你的寫好是按了對全部音源處理過一次。
的確覺得怪怪的。
只是我不清楚你實際要的做法。所以沒辦法跟你說對還是錯。

小斑 iT邦新手 4 級 ‧ 2020-04-09 15:40:41 檢舉

感謝提醒 id 名稱不能重覆,我再想想怎麼來改。另外,目前的確好像是按了按鈕後會對全部音源處理過一次,這部分我也有覺得怪怪的,我的實際做法應該是要各自按鈕控制各自音源才對。><

我要發表回答

立即登入回答