简体   繁体   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

Here is the important piece of TS code that trys so find a video-file locate in the R2-Storage from CloudFlare.这是一段重要的 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
});

The goal is, that an Android-Mediaplayer can access the worker-url which runs the above code and gets back the video source.目标是, Android-Mediaplayer可以访问运行上述代码的 worker-url 并取回视频源。

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

Unfortunately this doesn't work out of the box.不幸的是,这不是开箱即用的。 The Mediaplayer accepts the url, but throws an error event : Mediaplayer 接受 url,但抛出一个错误事件
response code = 200响应代码 = 200
W/MediaHTTPConnection: readAt 3273303 / 32768 => java.net.ProtocolException W/MediaHTTPConnection: readAt 3273303 / 32768 => java.net.ProtocolException
I/http: on error: 1 -2147483648 I/http: 错误:1 -2147483648

I can't find much information what's going on, so i'll appreciate all help.我找不到太多信息,所以我会感谢所有帮助。

Im wondering if there's a part which im missing, for example a valid cors header etc.. Current situation is,我想知道我是否缺少一部分,例如有效的 cors header 等。目前的情况是,

  • that the given worker-url runs correct in a chrome browser.给定的 worker-url 在 chrome 浏览器中运行正确。
  • Safari doesn't play the video and give me an error (Failed to load resource: ...) Safari 不播放视频并给我一个错误(无法加载资源:...)
  • The following curl command also downloads the desired video file correct, which tells me that downloading the file kinda works.以下 curl 命令也可以正确下载所需的视频文件,这告诉我下载文件还算有效。
curl http://127.0.0.1:8787/r2/video/{id}/video.mp4/{hash}> test.mp4

In case anyone has the same problem:如果有人有同样的问题:

The problem is, you need to have a partial content response (status code 206).问题是,您需要有部分内容响应(状态代码 206)。

If you google it, there a some headers you have to set.如果你用谷歌搜索它,你必须设置一些标题。

In order to fix this issue, you need to extract the range from the request and respond with a 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,
    });

Another usefull link: AVPlayer with 206另一个有用的链接: AVPlayer with 206

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM