0

내 서버에서 클라이언트 측으로 mp3 데이터를 스트리밍하려고합니다. 나는 Ajax를 사용하여 이것을하고있다. 서버는 요청 당 50KB를 보냅니다. 필자는 두 가지 기능을 썼습니다. 하나는 mp3 데이터를 가져오고 하나는 mp3 데이터를 재생합니다. 첫 번째 함수는 50 킬로바이트를 사용하여 디코드 한 다음 디코드 된 데이터를 배열에 저장 한 다음 재귀 적으로 호출합니다. 두 번째 함수는 배열의 첫 번째 요소가 데이터로 채워지 자마자 재생을 시작합니다. 문제는 처음 50 킬로바이트에서만 작동한다는 것입니다. 내가하고 싶은 일은 서버가 보낼 데이터가 더 이상 없다고 알리고 배열에 더 이상 요소가 없을 때까지 데이터를 재생하는 내 play() 함수를 유지할 때까지 get_buffer 함수를 계속 실행하는 것입니다.자바 스크립트의 비동기식 재귀 함수

function buffer_seg() { 
    // starts a new request 
    buff_req = new XMLHttpRequest(); 

    // Request attributes 
    var method = 'GET'; 
    var url = '/buffer.php?request=buffer&offset=' + offset; 
    var async = true; 

    // set attributes 
    buff_req.open(method, url, async); 
    buff_req.responseType = 'arraybuffer'; 

    // keeps loading until something is recieved 
    if (!loaded) { 
     change_icon(); 
     buffering = true; 

    } 


    buff_req.onload = function() { 
     segment = buff_req.response; 

     // if the whole file was already buffered 
     if (segment.byteLength == 4) { 
      return true; 
     } else if (segment.byteLength == 3) { 
      return false; 
     } 
     // sets the new offset 
     if (offset == -1) { 
      offset = BUFFER_SIZE; 
     } else { 
      offset += BUFFER_SIZE; 
     } 
     //decodes mp3 data and adds it to the array 
     audioContext.decodeAudioData(segment, function(decoded) { 
      buffer.push(decoded); 
      debugger; 
      if (index == 0) { 
       play(); 
      } 

     }); 


    } 
    buff_req.send(); 
    buff_seg(); 
} 

두 번째 기능 : 여기

내 두 가지 기능입니다

function play() { 

    // checks if the end of buffer has been reached 
    if (index == buffer.length) { 
     loaded = false; 
     change_icon(); 
     if (buffer_seg == false) { 
      stop(); 
      change_icon(); 
      return false; 
     } 
    } 
    loaded = true; 
    change_icon(); 

    // new buffer source 
    var src = audioContext.createBufferSource(); 

    src.buffer = buffer[index++]; 

    // connects 
    src.connect(audioContext.destination); 

    src.start(time); 
    time += src.buffer.duration; 
    src.onended = function() { 
     src.disconnect(audioContext.destination); 
     play(); 
    } 

} 

답변

0

buffer_seg에 재귀 호출이 buffer_seg의 본체에,하지 콜백에서 즉시 발생하므로 - 응답을받은 후에 의도 한 것처럼 보이지 않습니다. 둘째, 이전 응답에서 더 많은 데이터를 사용할 수 있는지 여부를 기반으로 할 때 재귀 호출이 무조건 수행된다는 것을 의미합니다. 이게 단지 브라우저를 망치는 것이 아니라면, 왜 그런지 모르겠습니다. 또한 스트리밍 된 오디오 덩어리가 순서대로 버퍼에 푸시 될 수 있음을 의미합니다.

시작하려면 스트림 끝 확인 후 onload 처리기 끝으로 재귀 호출을 이동하는 것이 좋습니다.

두 번째 기능에서 무엇을 할 예정입니까? if (buffer_seg == false)? 이 조건은 결코 충족되지 않습니다. 이 값이 buffer_seg의 마지막 반환 값을 확인하는 방법이라고 생각하십니까? 그것이 작동하는 방식이 아닙니다. 아마도 두 함수가 볼 수있는 변수가 있어야합니다. buffer_seg을 설정하고 play을 테스트 할 수 있습니다.

+0

"offset"변수는 서버가 mp3 오디오를 보낸 바이트를 시작하는 것을 서버에 알려줍니다. 따라서 오프셋은 파일 끝나 파일 끝나면 ​​보내집니다 "답장"으로 서버가 응답합니다. arraybuffer의 크기가 "done"보다 4보다 큰지 확인합니다. false를 반환합니다. 미안 해요, 내 버퍼가 있어야합니다 (buffer_seg() == false). buffer_seg() 함수가 배열의 끝에 도달하면 buffer_seg가 새 데이터를 버퍼링하는지 확인하거나 EOF를 나타내는 false를 반환합니다. 답장을 보내 주셔서 감사합니다. –

+0

네, 오프셋하려는 의도를 알고 있습니다. 왜 당신이 이것을 지적하고 있는지 나는 확신 할 수 없다. 코드를 작성한 것처럼 응답이 순서대로 되돌아 올 수있는 것은 변하지 않습니다. 또한'(buffer_seg() == false)'는'buffer_seg'에 대한 호출이 절대로 돌아 오지 않기 때문에 더 잘 작동하지 않을 것입니다. 'buffer_seg' 자체를 호출했기 때문에 어떤 경우에도'play'라고하는 점이 없다. –

+0

그래, 나는 당신의 요점에 동의, 어떻게 스크립트가 올바르게 실행되지 않을 수 있습니다 나는 심지어이 문제의 일부를 이미 수정 볼 수 있습니다. 그러나 스트리밍 데이터를 백그라운드로 유지하고 배열에 저장하는 함수와 배열을 읽고 저장하는 함수를 작성하는 방법에 대한 제안이 있습니까? 아니면 전체 버퍼링이 끝나기 전에 mp3 바이너리 데이터를 어떻게 버퍼링하고 재생할 수 있습니까? –