>

나는 방출하려고합니다 webm Blob s (Base64 인코딩 및 생성 MediaRecorder )를 WS를 통해 Phoenix 백엔드에 추가합니다. 여기서는 Base64 디코딩하여 파일에 추가합니다. 내가 끝내는 것은 결함있는 webm 비디오입니다. 플레이어에서 열면 첫 번째 프레임을 볼 수 있지만 약간 픽셀 화되고 색상이 꺼집니다. 비디오 길이가 존재하지 않으며 진단하려고 할 때 와 오류 ffmpeg , 그것은 말합니다 :

[h264 @ 0x7fcbd3804200] decode_slice_header error
[h264 @ 0x7fcbd3804200] no frame!
[h264 @ 0x7fcbd3804200] non-existing PPS 0 referenced
(repeated many times)

어디에서 오류가 발생했는지 확실하지 않은지 (또는 오류가 발생했는지) 확실하지 않은 클라이언트 쪽 코드는 다음과 같습니다.

const mediaStream = await navigator.mediaDevices.getUserMedia({ audio:true, video: true });
const options = {
  audioBitsPerSecond: 128000,
  videoBitsPerSecond: 2500000,
  mimeType: 'video/webm'
}
const mediaRecorder = new MediaRecorder(mediaStream,options);
mediaRecorder.ondataavailable = ((e) => {
  var reader = new window.FileReader();
  reader.readAsDataURL(e.data);
  reader.onloadend = (() => {
    base64data = reader.result;
    topic.push('video_feed', {data: base64data});
  })
})
mediaRecorder.start(1500);

파일 IO 및 Base64 디코딩을 담당하는 백엔드 Elixir 코드 :

{:ok, io} = File.open("some_file.webm", [:binary, :append]) # This part is triggered once
# Everything below is triggered upon receiving a blob (feed is the base64data object from 
# clientside code above)
"data:video/x-matroska;codecs=avc1,opus;base64," <> base64_bit = feed
decode_res = Base.decode64(base64_bit)
case decode_res do
  :error -> some_error_handling_code
  {:ok, data} -> io |> IO.binwrite(data)
end
{:noreply, state}

어떻게 든 파일 IO를 엉망으로 만들고 있습니까? 미디어 플레이어에 필요한 일부 헤더 또는 파일 메타 데이터가 누락 된 것으로 의심됩니다.

  • 답변 # 1

    좋아, 이틀을 파고 디버깅 한 후 webm 파일, 이것이 클라이언트 측 문제 (코드 관련)임을 깨달았습니다.

    호출 직후 클라이언트 측에서 소켓을 닫은 경쟁 조건이있었습니다. mediaRecorder.stop() . 내가 잊었을 때 이것은 실수였다이 경우 최종 데이터는 항상 나머지 데이터와 함께 생성됩니다.(마지막 방출 시간과 레코더 정지 시간 사이의 청크). 프로그래밍 방식으로 탭을 즉시 닫았을 때 해당 이벤트가 전송되지 않아서 비디오가 잘못되었습니다. 다른 코드 관련 문제가 있었지만 큰 문제는 없습니다.

    다음과 같은 최종 이벤트가 있는지 확인하십시오.

    topic.push('feed', {data: base64data})
      .receive('ok', () => {
        // MR state will become inactive as soon as you call .stop() method
        if (mediaRecorder.state === 'inactive') {
          x.push('that_was_the_final_chunk_go_wild', {}).receive('ok' => {
            nowWeCanSurelySafelyTerminate();
          })
        }
      })
    }
    
    

  • 이전 Angular에서 속성 바인딩을 사용하지 않고 부모와 자식 사이에 통신하는 방법은 무엇입니까?
  • 다음 Problem with the splashscreen after resume ( Flutter - 재개 후 스플래시 화면 문제 (flutter - 안드로이드)