In my web application, I have a requirement to play part of an mp3 file. This is a local web application, so I'm not interested in downloads, etc. Everything is stored locally.
My use case is as follows:
- define file to play
- determine the start and stop of sound
- upload file [I use BufferLoader]
- the game
Pretty simple.
Right now, I'm just grabbing an mp3 file, decrypting it in memory for use with the WebAudio API, and playing it back. Unfortunately, due to the fact that mp3 files can be quite long [30 minutes of audio, for example], a decoded file in memory can take up to 900 MB. This is too much to handle.
Is there an option where I could decode only part of the file? How can I determine where to start and how far to go? I can not predict the bitrate, it can be constant, but I would also expect a variable.
Here is an example of what I did: http://tinyurl.com/z9vjy34
Code [I tried to make it as compact as possible):
var MediaPlayerAudioContext = window.AudioContext || window.webkitAudioContext; var MediaPlayer = function () { this.mediaPlayerAudioContext = new MediaPlayerAudioContext(); this.currentTextItem = 0; this.playing = false; this.active = false; this.currentPage = null; this.currentAudioTrack = 0; }; MediaPlayer.prototype.setPageNumber = function (page_number) { this.pageTotalNumber = page_number }; MediaPlayer.prototype.generateAudioTracks = function () { var audioTracks = []; var currentBegin; var currentEnd; var currentPath; audioTracks[0] = { begin: 4.300, end: 10.000, path: "example.mp3" }; this.currentPageAudioTracks = audioTracks; }; MediaPlayer.prototype.show = function () { this.mediaPlayerAudioContext = new MediaPlayerAudioContext(); }; MediaPlayer.prototype.hide = function () { if (this.playing) { this.stop(); } this.mediaPlayerAudioContext = null; this.active = false; }; MediaPlayer.prototype.play = function () { this.stopped = false; console.trace(); this.playMediaPlayer(); }; MediaPlayer.prototype.playbackStarted = function() { this.playing = true; }; MediaPlayer.prototype.playMediaPlayer = function () { var instance = this; var audioTrack = this.currentPageAudioTracks[this.currentAudioTrack]; var newBufferPath = audioTrack.path; if (this.mediaPlayerBufferPath && this.mediaPlayerBufferPath === newBufferPath) { this.currentBufferSource = this.mediaPlayerAudioContext.createBufferSource(); this.currentBufferSource.buffer = this.mediaPlayerBuffer; this.currentBufferSource.connect(this.mediaPlayerAudioContext.destination); this.currentBufferSource.onended = function () { instance.currentBufferSource.disconnect(0); instance.audioTrackFinishedPlaying() }; this.playing = true; this.currentBufferSource.start(0, audioTrack.begin, audioTrack.end - audioTrack.begin); this.currentAudioStartTimeInAudioContext = this.mediaPlayerAudioContext.currentTime; this.currentAudioStartTimeOffset = audioTrack.begin; this.currentTrackStartTime = this.mediaPlayerAudioContext.currentTime - (this.currentTrackResumeOffset || 0); this.currentTrackResumeOffset = null; } else { function finishedLoading(bufferList) { instance.mediaPlayerBuffer = bufferList[0]; instance.playMediaPlayer(); } if (this.currentBufferSource){ this.currentBufferSource.disconnect(0); this.currentBufferSource.stop(0); this.currentBufferSource = null; } this.mediaPlayerBuffer = null; this.mediaPlayerBufferPath = newBufferPath; this.bufferLoader = new BufferLoader(this.mediaPlayerAudioContext, [this.mediaPlayerBufferPath], finishedLoading); this.bufferLoader.load(); } }; MediaPlayer.prototype.stop = function () { this.stopped = true; if (this.currentBufferSource) { this.currentBufferSource.onended = null; this.currentBufferSource.disconnect(0); this.currentBufferSource.stop(0); this.currentBufferSource = null; } this.bufferLoader = null; this.mediaPlayerBuffer = null; this.mediaPlayerBufferPath = null; this.currentTrackStartTime = null; this.currentTrackResumeOffset = null; this.currentAudioTrack = 0; if (this.currentTextTimeout) { clearTimeout(this.currentTextTimeout); this.textHighlightFinished(); this.currentTextTimeout = null; this.currentTextItem = null; } this.playing = false; }; MediaPlayer.prototype.getNumberOfPages = function () { return this.pageTotalNumber; }; MediaPlayer.prototype.playbackFinished = function () { this.currentAudioTrack = 0; this.playing = false; }; MediaPlayer.prototype.audioTrackFinishedPlaying = function () { this.currentAudioTrack++; if (this.currentAudioTrack >= this.currentPageAudioTracks.length) { this.playbackFinished(); } else { this.playMediaPlayer(); } };
source share