Safari에서 첫 클릭 시 Secure media 오디오가 재생되지 않음

(2.5.0 안정판 업데이트 이후로) Safari에서 보안 미디어 오디오 파일이 첫 클릭 시 재생되지 않습니다. 오디오를 시작하려면 재생 아이콘을 두세 번 클릭해야 합니다. 첫 클릭 시에는 웹 서버에 요청이 전송되지 않으며, 대략 세 번째 클릭에서야 요청이 전송됩니다.

Safari에서만 발생하는 브라우저 문제인 것 같지만, 2.5.0 업데이트 전후로 이런 현상이 시작되었다는 점이 다소 의심스럽습니다.

유사한 경험을 하신 분이 계신가요?

이것과 관련이 있는지 확실하지 않습니다. 보안 미디어 업로드 만료

@martin 여기 대해 혹시 아이디어가 있나요?

내일 확인해 볼게. 거기서 두세 번의 클릭이 필요하다고 하면 사파리 문제인 것 같네. 내 아이폰으로 테스트해 봐야겠다.

iOS에서 Safari와 Firefox 모두에서 이 문제가 버그임을 확인했습니다. 여러 번 재생/일시정지를 해야만 오디오가 재생됩니다. 위젯 컴포넌트는 두 브라우저에서 모두 동일하게 보입니다(모바일 Firefox가 모바일 Safari 렌더링 엔진을 감싸는 래퍼일 뿐이라고 _생각_합니다). iOS 13.5.1에서 테스트했습니다.

WebKit 버그 트래커에는 최근 발생한 오디오 관련 이슈가 꽤 많지만, 이 중 관련이 있는 것이 있는지 확실하지 않습니다. https://bugs.webkit.org/buglist.cgi?bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&field0-0-0=product&field0-0-1=component&field0-0-2=alias&field0-0-3=short_desc&field0-0-4=status_whiteboard&field0-0-5=content&no_redirect=1&order=changeddate%20DESC%2Cbug_status%2Cpriority%2Cassigned_to%2Cbug_id&query_format=advanced&type0-0-0=substring&type0-0-1=substring&type0-0-2=substring&type0-0-3=substring&type0-0-4=substring&type0-0-5=matches&value0-0-0=audio&value0-0-1=audio&value0-0-2=audio&value0-0-3=audio&value0-0-4=audio&value0-0-5="audio".

이 w3schools 오디오 클립은 iOS Safari와 Firefox에서 정상적으로 재생됩니다. W3Schools Tryit Editor. 문제가 preload="none"를 사용했기 때문일 수도 있습니다. 제가 생각할 수 있는 유일한 차이점입니다… 또는 보안 미디어 URL을 실제 오디오 URL로 302 리다이렉트하는 것이 문제를 일으키는 것일까요?

리다이렉트가 문제의 원인이라고 생각하게 된 몇 가지 단서:

처음 클릭할 때 서버로 요청이 발화되지 않는 것으로 보아, 문제는 302 리다이렉트보다 이전 단계에 있는 것 같습니다…

@martin 이 문제에 대해 뭔가 찾았나요?

불행히도 다른 프로젝트에 바빠서 아직 진행하지 못했습니다. 다만 이 항목은 제 목록에 있고, 곧 더 자세히 살펴볼 예정입니다. 내부적으로도 비슷한 문제에 대해 간단히 논의한 적이 있습니다.

지금까지 꽤 모험적인 과정이었네요. 결국에는 Ubuntu 기기의 Chrome과 iPhone의 iOS Safari 간 원격 디버깅을 설정하는 데 성공했지만, 그 과정은 험난했습니다. 그러나 안타깝게도 Network 탭이 비어 있는데, 이 경우 가장 중요한 부분이 바로 이 탭이라 좀 짜증스럽습니다.

preload="metadata"로 설정하면 iOS Safari에서 첫 번째 클릭 시 오디오가 재생되는 것을 확인했습니다. 반면 preload="none"으로 설정하면 실제로 오디오를 재생하려면 Play > Pause > Play 순서를 거쳐야 합니다.

video 태그로도 테스트해 보았는데, 비슷한 문제가 존재하는 것으로 보입니다.

preload="none"으로 변경한 이유는 여기 있는 버그 보고서(Secure media uploads expire) 때문입니다. 지금은 preload를 metadata로 되돌리면 위에서 언급한 문제가 다시 발생하기 때문에, 다소 번거로운 회색 지대에 놓여 있습니다. 최근 presigned URL 만료 시간을 5분으로 늘렸습니다(FIX: Increase time of DOWNLOAD_URL_EXPIRES_AFTER_SECONDS to 5 minutes - Pull Request #10160 - discourse/discourse - GitHub) 덕분에 원래의 버그는 덜 심각한 문제가 되었지만… 여전히 문제입니다.

아직 이 문제에 대해 고민하고 이것저것 시도해 보고 있습니다. 두 가지 모두를 만족시킬 수 있을지 확신이 서지 않습니다. 보안 미디어를 보기 위해 여러 번 클릭해야 하는 것은 이상적인 경험이 아닙니다.

수정: 디버거의 Network 탭을 작동시키는 데 성공했습니다. 내부 Discourse 인스턴스에서 preload="none"이 설정된 audio 태그에 대한 예시입니다:

  1. 재생 버튼 누름: GET /secure-media-uploads/meta/dev/original/4X/6/1/8/618a6b19a07de18205cc9889cb604e414b30372b.mp3 요청이 Finished 상태로 반환됩니다.

  2. 일시정지 버튼 누름.

  3. 재생 버튼 누름: GET presigned_url_here 요청이 206 Partial Content 상태로 반환되고, 오디오가 정상적으로 로드됩니다.

여기서 이상한 점은 preload="metadata"인 경우에도 동일한 요청 시퀀스가 발생한다는 것입니다. 단, 재생 클릭은 한 번만 하면 됩니다. Safari가 첫 번째 재생 클릭 시 메타데이터를 가져오고, 오디오를 재생하려면 다시 일시정지 후 재생을 해야 하는 것처럼 보입니다.

이것이 Android 등 다른 기기에서도 발생하는지 확신이 서지 않습니다. 해당 기기로 테스트할 장치가 없기 때문입니다.

훌륭한 디버깅 세션이네요!

한 가지 질문이 있습니다:

이 응답은 어떤 모습인가요? Finished는 HTTP 응답 코드가 아니죠?

감사합니다!

좋은 질문입니다! 네, 맞습니다. Finished는 상태 코드가 아닙니다. 여기서 네트워크 탭에서 추가 정보를 얻을 수 없습니다:

크기는 0B이고 시간은 0ms입니다.

이것이 mitmproxy를 설정하여 여기서 무슨 일이 일어나고 있는지 다시 살펴보는 계기가 되었습니다. 첫 번째 “Finished” 요청은 iOS 기기/사파리 브라우저에서 나가지 않는 것 같습니다. mitm 프록시는 PLAY를 두 번째로 클릭할 때까지 아무것도 기록하지 않습니다.

Safari(iOS 및 데스크톱 모두, 데스크톱에서도 재현 가능)에는 preload="metadata"를, 그 외 브라우저에는 preload="none"을 사용하는 것이 합리적일까요?

(또한, 제 경우 안드로이드에서는 PWA로 테스트해 봤는데 이런 현상이 일어나지 않는 것 같습니다.)

네, 그 방향으로 진행해야 할 것 같습니다. Android와 데스크톱 Safari에서도 테스트해 주셔서 감사합니다. 현재 preload 속성은 지원되지 않는 상태이므로, 브라우저가 Safari인지 감지하여 preload 속성을 대체하는 클라이언트 사이드 코드가 필요할 것 같습니다. 오늘 이 부분에 대해 몇 가지 실험을 해 보겠습니다.

제가 이 문제를 올바르게 이해하고 있는지 확인하고 싶은데, 이 버그는 Safari가 다운로드 청크 분할 지점을 5분 시점 이후에 설정하는 오디오에서 다시 나타나는 건가요?

네, 하지만 이 새로운 수정 사항으로 인해 미디어가 포함된 게시물이 화면에 표시될 때(예: 스크롤을 통해) preload 속성만 변경하면 이 문제를 우회할 수 있을 것 같습니다. 문제는 보안 미디어 URL에서 메타데이터를 가져온 후 서명된 URL이 생성되어 플레이어에 사용되는데, 이 URL은 5분 후에 만료된다는 점입니다. 따라서 5분 이내에 재생을 누르지 않으면 URL이 만료됩니다.

JS를 사용하여 미디어를 재생했다가 일시 정지하면, 나중에 전송되는 206 부분 콘텐츠 요청에 차이를 만들 수 있는지 궁금합니다. 서명된 URL의 만료에 구애받지 않는 것으로 보이는 요청이므로요. 물론 제 추측일 수 있으며, 더 많은 테스트가 필요합니다.

수정: Android 기기에 Chrome을 사용하여 직접 확인해 본 결과, 해당 기기에서는 이 문제가 발생하지 않는 것을 확인했습니다.

@martinwoodward님의 승인으로, 오늘 모든 컨텍스트에서(보안 미디어 포함) 모든 오디오/비디오 요소에 대해 preload="metadata"를 사용하도록 전환하는 몇 가지 커밋을 진행했습니다. 이 변경 사항은 여기에서 설명된 문제를 수정해야 합니다.

참고: 사용자가 5분 이상 해당 페이지에 머무르면, 보안 URL이 현재 5분만 유효하기 때문에 오디오/비디오를 재생할 수 없을 가능성이 높습니다.

늦게 답변드려 죄송합니다. 이 문제는 이제 실제로 수정되었습니다 :tada:

@pmusaraj님과 @martin님께 감사드립니다!