簡體   English   中英

通過 CloudFlare Workers 發送 R2 視頻 Stream 導致 Android MediaPlayer 和 Safari 崩潰

[英]Sending an R2 Video Stream through CloudFlare Workers leads to a crash in Android MediaPlayer and Safari

這是一段重要的 TS 代碼,它試圖在 CloudFlare 的R2-Storage中找到一個視頻文件。

const { id, ref, hash } = req.param();
if (!await isHashValid(hash))
  return c.text("Unauthorized", 401);

const file: R2ObjectBody = await AR_POSTCARDS.get(`${id}/${ref}`);
if (file === null) return new Response("Object Not Found", { status: 404 });
const headers = new Headers();
file.writeHttpMetadata(headers);
headers.set("etag", file.httpEtag);
headers.set("Content-Type", "video/mp4");

const { readable, writable } = new TransformStream();
file.body?.pipeTo(writable);
return new Response(readable, {
   headers
});

目標是, Android-Mediaplayer可以訪問運行上述代碼的 worker-url 並取回視頻源。

  mediaPlayer = new MediaPlayer();
  mediaPlayer.setDataSource(url);

不幸的是,這不是開箱即用的。 Mediaplayer 接受 url,但拋出一個錯誤事件
響應代碼 = 200
W/MediaHTTPConnection: readAt 3273303 / 32768 => java.net.ProtocolException
I/http: 錯誤:1 -2147483648

我找不到太多信息,所以我會感謝所有幫助。

我想知道我是否缺少一部分,例如有效的 cors header 等。目前的情況是,

  • 給定的 worker-url 在 chrome 瀏覽器中運行正確。
  • Safari 不播放視頻並給我一個錯誤(無法加載資源:...)
  • 以下 curl 命令也可以正確下載所需的視頻文件,這告訴我下載文件還算有效。
curl http://127.0.0.1:8787/r2/video/{id}/video.mp4/{hash}> test.mp4

如果有人有同樣的問題:

問題是,您需要有部分內容響應(狀態代碼 206)。

如果你用谷歌搜索它,你必須設置一些標題。

為了解決此問題,您需要從請求中提取范圍並使用 206 進行響應:

  const { id, ref } = c.req.param();

  // get start and end from range header
  const range = c.req.header("Range");
  const startEnd : number[] = range?.replace('bytes=', '')?.split('-')?.map(val => parseInt(val));
  const [start, end] = startEnd ?? [0, 1];

  try {
    const options: R2GetOptions = {
      range: {
        offset: start,
        length: end-start,
      }
    };
    const file: R2ObjectBody = await R2_BUCKET.get(`${id}/${ref}`, options);
    if (file === null) return new Response("Object Not Found", { status: 404 });

    const headers = new Headers();
    file.writeHttpMetadata(headers);
    headers.set("etag", file.httpEtag);
    headers.set("Content-Type", "video/mp4");
    headers.set("Accept-Ranges", "bytes");
    headers.set("Content-Range", `bytes ${start ?? 0}-${end ?? 1}/${file.size}`);
    headers.set("Content-Length", `${end - start}`);
    

    return new Response(file.body, {
      headers,
      status: 206,
    });

另一個有用的鏈接: AVPlayer with 206

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM