|
@@ -1,382 +0,0 @@
|
|
|
-/** 播放多个音频 */
|
|
|
-export default class MultipleAudio {
|
|
|
-
|
|
|
- audios: any = {}
|
|
|
-
|
|
|
- audioList: string[] = []
|
|
|
-
|
|
|
- length: number = 0
|
|
|
-
|
|
|
- status: 'init' | 'play' | 'pause' = 'init'
|
|
|
-
|
|
|
- speed: number = 90
|
|
|
-
|
|
|
- muted: boolean = false
|
|
|
-
|
|
|
- audio: null | HTMLAudioElement = null
|
|
|
-
|
|
|
-
|
|
|
- // group = new Pizzicato.Group([])
|
|
|
-
|
|
|
- currentTime: number = 0
|
|
|
-
|
|
|
- duration: number = 0
|
|
|
-
|
|
|
- timer: any = null
|
|
|
-
|
|
|
- accelerateRefreshPlayer = () => {
|
|
|
- if (this.timer) {
|
|
|
- return
|
|
|
- }
|
|
|
- const prevTime = this.currentTime
|
|
|
- let now = new Date().getTime()
|
|
|
- this.timer = setInterval(() => {
|
|
|
- this.currentTime = (new Date().getTime() - now) / 1000 + prevTime
|
|
|
- // console.log(this.currentTime)
|
|
|
- this.event.emit('timeupdate', this)
|
|
|
- }, 10)
|
|
|
- }
|
|
|
-
|
|
|
- clearAccelerateRefreshPlayer = () => {
|
|
|
- clearInterval(this.timer)
|
|
|
- this.timer = null
|
|
|
- }
|
|
|
-
|
|
|
- constructor(list: string[]) {
|
|
|
- this.setSongs(list)
|
|
|
- // this.event.on('timeupdate', () => {
|
|
|
- // console.log(this.currentTime)
|
|
|
- // })
|
|
|
- }
|
|
|
-
|
|
|
- async setSongs(list: string[]) {
|
|
|
- this.audioList = list.filter(item => !!item)
|
|
|
- this.audio = null
|
|
|
- this.audios = {}
|
|
|
- const filterReqs = list.filter(item => !!item).map(async url => ({
|
|
|
- // bolb: await request.get(url, {responseType: 'blob'}),
|
|
|
- url
|
|
|
- }))
|
|
|
- const res = await Promise.all(filterReqs)
|
|
|
- for (const item of res) {
|
|
|
- const audio = new Audio(item.url)
|
|
|
- // audio.controls = true
|
|
|
- // document.body.append(audio)
|
|
|
- audio.load()
|
|
|
- this.audios[item.url] = audio
|
|
|
- if (!this.audio) {
|
|
|
- this.audio = audio
|
|
|
- }
|
|
|
- }
|
|
|
- // console.log(filterReqs.length, this.audio)
|
|
|
- this.length = filterReqs.length
|
|
|
- if (this.audio) {
|
|
|
- this.audio.addEventListener('loadedmetadata', evt => {
|
|
|
- // this.duration = this.audio?.duration || 0
|
|
|
- // this.event.emit('loadedmetadata', evt, this.audio?.duration)
|
|
|
- this.setDuration()
|
|
|
- })
|
|
|
- this.audio.addEventListener('timeupdate', evt => {
|
|
|
- this.currentTime = this.audio?.currentTime || 0
|
|
|
- this.event.emit('timeupdate', evt)
|
|
|
- let used = false
|
|
|
- if (this.currentTime === this.duration && !used) {
|
|
|
- used = true
|
|
|
- // this.event.emit('ended')
|
|
|
- // this.audio?.dispatchEvent(endedEvent)
|
|
|
- // for (const key in this.audios) {
|
|
|
- // if (Object.prototype.hasOwnProperty.call(this.audios, key)) {
|
|
|
- // const audio = this.audios[key]
|
|
|
- // const endedEvent = new Event('ended')
|
|
|
- // audio.dispatchEvent(endedEvent)
|
|
|
- // }
|
|
|
- // }
|
|
|
- // console.log('ended')
|
|
|
- }
|
|
|
- })
|
|
|
- // this.audio.addEventListener('ended', () => {
|
|
|
- // this.setCurrentTime(0)
|
|
|
- // // this.play()
|
|
|
- // })
|
|
|
- }
|
|
|
- if (list.length) {
|
|
|
- this.status = this.getStatus()
|
|
|
- }
|
|
|
- this.event.on('allWaiting', () => {
|
|
|
- if (this.hasWaitng()) {
|
|
|
- this.event.emit('waiting')
|
|
|
- }
|
|
|
- })
|
|
|
- this.event.on('allPlaying', () => {
|
|
|
- if (!this.hasWaitng()) {
|
|
|
- this.event.emit('playing')
|
|
|
- }
|
|
|
- })
|
|
|
- this.syncEvent()
|
|
|
- }
|
|
|
-
|
|
|
- setDuration(aus?: any) {
|
|
|
- const audios: HTMLAudioElement[] = Object.values(aus || this.audios || {})
|
|
|
- if (audios.length) {
|
|
|
- const times: number[] = []
|
|
|
- for (const item of audios) {
|
|
|
- const duration = (item as HTMLAudioElement).duration
|
|
|
- if (duration > 0) {
|
|
|
- times.push(duration)
|
|
|
- }
|
|
|
- }
|
|
|
- const num = Math.floor(Math.max(...times) - Math.min(...times))
|
|
|
- if (num >= 1){
|
|
|
- console.log('该教程原音与伴奏时长超过' + num + '秒,请修改后使用')
|
|
|
- // Dialog.alert({
|
|
|
- // message: '该教程原音与伴奏时长超过' + num + '秒,请修改后使用',
|
|
|
- // })
|
|
|
- }
|
|
|
- this.duration = Math.min(...times)
|
|
|
-
|
|
|
- if (this.duration > 0) {
|
|
|
- this.event?.emit('loadedmetadata', null, this.duration)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- destroyed() {
|
|
|
- this.pause()
|
|
|
- this.event.removeAllListeners()
|
|
|
- this.audio = null
|
|
|
- // Object.values(this.audios).map(item => item.remove())
|
|
|
- this.audios = {}
|
|
|
- }
|
|
|
-
|
|
|
- hasWaitng() {
|
|
|
- let status = false
|
|
|
- for (const audio of Object.values(this.audios)) {
|
|
|
- if ((audio as any).dataset.status === 'waiting') {
|
|
|
- status = true
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- return status
|
|
|
- }
|
|
|
-
|
|
|
- syncEvent() {
|
|
|
- let isEnded = false
|
|
|
- const play = (evt: Event) => {
|
|
|
- isEnded = false
|
|
|
- // console.log('实际延迟', new Date().getTime() - starttime)
|
|
|
- // console.log('开始触发play事件', new Date().getTime())
|
|
|
- this.event.emit('play', evt)
|
|
|
- // console.log(this.audioList[0])
|
|
|
- if (compareURL((evt.target as HTMLAudioElement)?.src, this.audioList[0])) {
|
|
|
- playStartTime = new Date().getTime()
|
|
|
- }
|
|
|
- // this.play()
|
|
|
- }
|
|
|
- const pause = async (evt: Event) => {
|
|
|
- await this.pause()
|
|
|
- this.event.emit('pause', evt)
|
|
|
- if (compareURL((evt.target as HTMLAudioElement)?.src, this.audioList[0])) {
|
|
|
- const playTime = new Date().getTime() - playStartTime
|
|
|
- playStartTime = new Date().getTime()
|
|
|
- this.event.emit('updatePlayTime', playTime / 1000)
|
|
|
- }
|
|
|
- }
|
|
|
- const waiting = (evt: any) => {
|
|
|
- if (this.status === 'play') {
|
|
|
- evt.target.dataset.status = 'waiting'
|
|
|
- }
|
|
|
- this.event.emit('allWaiting')
|
|
|
- }
|
|
|
- const playing = (evt: any) => {
|
|
|
- evt.target.dataset.status = ''
|
|
|
- this.event.emit('allPlaying')
|
|
|
- }
|
|
|
- const ended = async (evt: Event) => {
|
|
|
- if (!isEnded) {
|
|
|
- isEnded = true
|
|
|
- await this.pause()
|
|
|
- }
|
|
|
- for (const key in this.audios) {
|
|
|
- if (Object.prototype.hasOwnProperty.call(this.audios, key)) {
|
|
|
- this.event.emit('ended', {
|
|
|
- target: this.audios[key]
|
|
|
- })
|
|
|
- // const audio = this.audios[key]
|
|
|
- // const endedEvent = new Event('ended')
|
|
|
- // audio.dispatchEvent(endedEvent)
|
|
|
- }
|
|
|
- }
|
|
|
- // this.event.emit('ended', evt)
|
|
|
- }
|
|
|
- // for (const audio of Object.values(this.audios)) {
|
|
|
- // audio.removeEventListener('play', play)
|
|
|
- // audio.removeEventListener('pause', pause)
|
|
|
- // audio.removeEventListener('waiting', waiting)
|
|
|
- // audio.removeEventListener('playing', playing)
|
|
|
- // audio.removeEventListener('ended', ended)
|
|
|
- // }
|
|
|
- for (const audio of Object.values(this.audios)) {
|
|
|
- (audio as HTMLAudioElement).addEventListener('loadedmetadata', () => this.setDuration(this.audios))
|
|
|
- ;(audio as HTMLAudioElement).addEventListener('play', play)
|
|
|
- ;(audio as HTMLAudioElement).addEventListener('pause', pause)
|
|
|
- ;(audio as HTMLAudioElement).addEventListener('waiting', waiting)
|
|
|
- ;(audio as HTMLAudioElement).addEventListener('playing', playing)
|
|
|
- ;(audio as HTMLAudioElement).addEventListener('ended', ended)
|
|
|
- }
|
|
|
- // this.audio?.addEventListener('play', play)
|
|
|
- // this.audio?.addEventListener('pause', pause)
|
|
|
- // this.audio?.addEventListener('waiting', waiting)
|
|
|
- // this.audio?.addEventListener('playing', playing)
|
|
|
- // this.audio?.addEventListener('ended', ended)
|
|
|
- }
|
|
|
-
|
|
|
- getStatus() {
|
|
|
- return !this.audio ? 'init' : this.audio?.paused ? 'pause' : 'play'
|
|
|
- }
|
|
|
-
|
|
|
- play(delay?: number) {
|
|
|
- let plused = false
|
|
|
- if (this.getStatus() !== 'play') {
|
|
|
- return new Promise((resolve) => {
|
|
|
- setTimeout(() => {
|
|
|
- starttime = new Date().getTime()
|
|
|
- Object.values(this.audios).map(async (item: any, inedx: number) => {
|
|
|
- // console.log('play duration', item.duration)
|
|
|
- await item.play()
|
|
|
- if (!plused) {
|
|
|
- plused = true
|
|
|
- // console.log('starttime', starttime)
|
|
|
- // console.log('延迟时间', new Date().getTime() - starttime)
|
|
|
- // runtime.evaluatingFixTime += new Date().getTime() - starttime
|
|
|
- }
|
|
|
- })
|
|
|
- resolve(this.audios)
|
|
|
- // Promise.all(Object.values(this.audios).map(async (item: any) => await item.play()))
|
|
|
- // .then(res => {
|
|
|
- // this.status = this.getStatus()
|
|
|
- // resolve(res)
|
|
|
- // return res
|
|
|
- // })
|
|
|
- }, (delay || 100))
|
|
|
- })
|
|
|
- }
|
|
|
- this.status = this.getStatus()
|
|
|
- return Promise.resolve()
|
|
|
- }
|
|
|
-
|
|
|
- pause() {
|
|
|
- this.status = this.getStatus()
|
|
|
- return Promise.all(Object.values(this.audios).map(async (item: any) => await item.pause()))
|
|
|
- .then(res => {
|
|
|
- this.status = this.getStatus()
|
|
|
- return res
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- setVolume = (none: boolean, cb: () => void) => {
|
|
|
- let timer = setInterval(() => {
|
|
|
- Object.values(this.audios).map((item: any) => {
|
|
|
- if (none) {
|
|
|
- item.volume -= 0.01
|
|
|
- if (item.volume <= 0.01) {
|
|
|
- item.volume = 0
|
|
|
- clearInterval(timer)
|
|
|
- cb && cb()
|
|
|
- }
|
|
|
- } else {
|
|
|
- item.volume += 0.01
|
|
|
- if (item.volume >= 1) {
|
|
|
- item.volume = 1
|
|
|
- clearInterval(timer)
|
|
|
- cb && cb()
|
|
|
- }
|
|
|
- }
|
|
|
- console.log(item.volume)
|
|
|
- })
|
|
|
- }, 16.7)
|
|
|
- }
|
|
|
-
|
|
|
- setMute(muted: boolean, url?: string) {
|
|
|
- if (url) {
|
|
|
- if (this.audios[url]) {
|
|
|
- // this.setVolume(muted, () => this.audios[url].muted = muted)
|
|
|
- this.audios[url].muted = muted
|
|
|
- // this.audios[url].volume = (muted ? 0 : 1)
|
|
|
- }
|
|
|
- } else {
|
|
|
- this.muted = muted
|
|
|
- // this.setVolume(muted, () => {
|
|
|
- Object.values(this.audios).map((item: any) => item.muted = muted)
|
|
|
- // })
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- setSpeed(speed: number, url?: string) {
|
|
|
- if (url) {
|
|
|
- if (this.audios[url]) {
|
|
|
- this.audios[url].playbackRate = speed
|
|
|
- // this.audios[url].speed = speed
|
|
|
- }
|
|
|
- } else {
|
|
|
- this.speed = speed
|
|
|
- // this.group.speed = speed
|
|
|
- Object.values(this.audios).map((item: any) => {
|
|
|
- item.playbackRate = speed
|
|
|
- // console.log(item.getSourceNode().playbackRate.value = speed)
|
|
|
- return item
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- setCurrentTime(time: number) {
|
|
|
- this.currentTime = time
|
|
|
- // if (this.status === 'play') {
|
|
|
- // this.pause()
|
|
|
- // this.play()
|
|
|
- // }
|
|
|
- Object.values(this.audios).map((item: any) => item.currentTime = time)
|
|
|
- }
|
|
|
-
|
|
|
- toggleMute(url?: string) {
|
|
|
- if (url) {
|
|
|
- if (this.audios[url]) {
|
|
|
- this.audios[url].muted = !this.audios[url].muted
|
|
|
- }
|
|
|
- } else {
|
|
|
- Object.values(this.audios).map((item: any) => item.muted = !this.muted)
|
|
|
- this.muted = !this.muted
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- togglePlay(delay?: number) {
|
|
|
- if (this.getStatus() === 'pause') {
|
|
|
- this.play(delay)
|
|
|
- } else if (this.getStatus() === 'play') {
|
|
|
- this.setMute(true)
|
|
|
- this.pause()
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-export interface IAudios {
|
|
|
- [key: string]: HTMLAudioElement
|
|
|
-}
|
|
|
-
|
|
|
-export interface IMultipleAudio {
|
|
|
- audios: IAudios
|
|
|
- audio: null | HTMLAudioElement
|
|
|
- status: string
|
|
|
- muted: boolean
|
|
|
- speed: number
|
|
|
- length: number
|
|
|
- event: EventEmitterType
|
|
|
- play(): void
|
|
|
- pause(): void
|
|
|
- setMute(muted: boolean, url?: string): void
|
|
|
- setSpeed(speed: number, url?: string): void
|
|
|
- togglePlay(): void
|
|
|
- toggleMute(): void
|
|
|
- setCurrentTime(time: number): void
|
|
|
- destroyed: () => void
|
|
|
-}
|