2016-02-16 21 views
5

私のウェブアプリケーションでは、mp3ファイルの一部を再生する必要があります。これはローカルのWebアプリケーションなので、ダウンロードなどは気にしません。すべてがローカルに保存されています。次のようにWebAudio APIで使用するmp3の一部のみをデコードする方法は?

私のユースケースは、次のとおりです。

  • を再生するファイルを決定したファイル[私はBufferLoaderを使用する]
を再生音
  • 負荷の開始と停止を決定します

    非常に簡単です。

    今私はちょうどmp3ファイルをつかみ、WebAudio APIで使用するためにメモリ内でデコードし、それを再生します。 残念ながら、mp3ファイルは非常に長く(例えば30分の音声)、メモリ内のデコードされたファイルは最大900MBを占めることがあります。それはあまりにも扱いにくいです。

    ファイルの一部だけをデコードできるオプションはありますか?どのように開始するのか、どこまで行くのかを検出するにはどうすればよいですか? 私はビットレートを予期することはできません、それは一定かもしれませんが、私は変数も期待しています。

    ここに私がやったことの一例です: http://tinyurl.com/z9vjy34

    コードは[私はできるだけコンパクトにそれを作るためにしようとしました]:

    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(); 
        } 
    }; 
    
    // 
    // 
    // Buffered Loader 
    // 
    // Class used to get the sound files 
    // 
    function BufferLoader(context, urlList, callback) { 
        this.context = context; 
        this.urlList = urlList; 
        this.onload = callback; 
        this.bufferList = []; 
        this.loadCount = 0; 
    } 
    
    // this allows us to handle media files with embedded artwork/id3 tags 
    function syncStream(node) { // should be done by api itself. and hopefully will. 
        var buf8 = new Uint8Array(node.buf); 
        buf8.indexOf = Array.prototype.indexOf; 
        var i = node.sync, b = buf8; 
        while (1) { 
         node.retry++; 
         i = b.indexOf(0xFF, i); 
         if (i == -1 || (b[i + 1] & 0xE0 == 0xE0)) break; 
         i++; 
        } 
        if (i != -1) { 
         var tmp = node.buf.slice(i); //carefull there it returns copy 
         delete(node.buf); 
         node.buf = null; 
         node.buf = tmp; 
         node.sync = i; 
         return true; 
        } 
        return false; 
    } 
    
    BufferLoader.prototype.loadBuffer = function (url, index) { 
        // Load buffer asynchronously 
        var request = new XMLHttpRequest(); 
        request.open("GET", url, true); 
        request.responseType = "arraybuffer"; 
    
        var loader = this; 
    
        function decode(sound) { 
         loader.context.decodeAudioData(
           sound.buf, 
           function (buffer) { 
            if (!buffer) { 
             alert('error decoding file data'); 
             return 
            } 
            loader.bufferList[index] = buffer; 
            if (++loader.loadCount == loader.urlList.length) 
             loader.onload(loader.bufferList); 
           }, 
           function (error) { 
            if (syncStream(sound)) { 
             decode(sound); 
            } else { 
             console.error('decodeAudioData error', error); 
            } 
           } 
         ); 
        } 
    
        request.onload = function() { 
         // Asynchronously decode the audio file data in request.response 
         var sound = {}; 
         sound.buf = request.response; 
         sound.sync = 0; 
         sound.retry = 0; 
         decode(sound); 
        }; 
        request.onerror = function() { 
         alert('BufferLoader: XHR error'); 
        }; 
        request.send(); 
    }; 
    
    BufferLoader.prototype.load = function() { 
        for (var i = 0; i < this.urlList.length; ++i) 
         this.loadBuffer(this.urlList[i], i); 
    }; 
    
  • +0

    MP3をWAVファイルに変換していますか? 900MBはナットです。 – zer00ne

    +0

    私はmp3を直接使う方法は見つけられませんでしたが、いつもそれを解読する必要があります。 – Krystian

    +0

    あなたは 'audio'タグを使わない方がいいでしょうか? –

    答えて

    1

    decodeAudioDataとストリーミングの手立ては(ありません)、あなたはcreateMediaStreamSourceでMediaElementを使用し、次にあなたのものを実行する必要があります。 decodeAudioData()はパーツでストリーミングできません@ zre00neそしてmp3は大きなデコードされます!!!とても大きい!!!

    +0

    そうです、そうです。 20MB mp3は900MBになりますPCM:/ – Krystian

    関連する問題