question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Videos hosted on worker sites not playing on iOS

See original GitHub issue

🐛 Bug Report

Environment

  • operating system: mac os
  • output of rustc -V: rustc 1.26.2
  • output of node -v: v10.16.3
  • output of wrangler -V: 👷 ✨ wrangler 1.6.0

Steps to reproduce

I created a worker site with wrangler generate --site test-mp4 and replaced the wrangler ferris image with a looping mp4.

The looping mp4 plays correctly on all devices except for iOS. I think this might be due to the worker not handling ranged requests, and iOS requiring ranged requests for video playback (https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/CreatingVideoforSafarioniPhone/CreatingVideoforSafarioniPhone.html#//apple_ref/doc/uid/TP40006514-SW6)

Try it out on your iPhone here -> https://test-mp4.tappable.workers.dev

What did you expect to see?

A video playing

What did you see instead?

A broken video indicator

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

3reactions
cpauwelscommented, Dec 6, 2019

@shagamemnon and anyone who might need to fix this now, here’s how I solved the issue:

const serveRange = async function(request, response) {
  if (!request.headers.get('range')) {
    console.log('no range')
    return response
  }

  const normalizedRangeHeader = request.headers
    .get('range')
    .trim()
    .toLowerCase()
  if (!normalizedRangeHeader.startsWith('bytes=')) {
    console.log('unit must be bytes')
    return response
  }

  if (normalizedRangeHeader.includes(',')) {
    console.log('single range only')
    return response
  }

  const rangeParts = /(\d*)-(\d*)/.exec(normalizedRangeHeader)
  // We need either at least one of the start or end values.
  if (!rangeParts || !(rangeParts[1] || rangeParts[2])) {
    console.log('invalid range values')
    return response
  }

  const start = rangeParts[1] === '' ? undefined : Number(rangeParts[1])
  const end = rangeParts[2] === '' ? undefined : Number(rangeParts[2])

  const originalBuffer = await response.arrayBuffer()
  const bufferSize = originalBuffer.byteLength
  if ((end && end > bufferSize) || (start && start < 0)) {
    console.log('range not satisfiable')
    return response
  }

  let effectiveStart
  let effectiveEnd

  if (start !== undefined && end !== undefined) {
    effectiveStart = start
    // Range values are inclusive, so add 1 to the value.
    effectiveEnd = end + 1
  } else if (start !== undefined && end === undefined) {
    effectiveStart = start
    effectiveEnd = bufferSize
  } else if (end !== undefined && start === undefined) {
    effectiveStart = bufferSize - end
    effectiveEnd = bufferSize
  }
  console.log(`range ${effectiveStart} - ${effectiveEnd}`)

  const slicedBuffer = originalBuffer.slice(effectiveStart, effectiveEnd)

  const slicedResponse = new Response(slicedBuffer, {
    // Status code 206 is for a Partial Content response.
    // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/206
    status: 206,
    statusText: 'Partial Content',
    headers: response.headers,
  })
  slicedResponse.headers.set('Content-Length', String(slicedBuffer.byteLength))
  slicedResponse.headers.set(
    'Content-Range',
    `bytes ${effectiveStart}-${effectiveEnd - 1}/` + bufferSize,
  )

  return slicedResponse
}

My only worry with this solution is wether I could run into some memory issues since the whole response is loaded in an ArrayBuffer and videos could be quite large… I’m guessing with worker sites the max size that can be stored in KV storage is 10MB and hence there won’t be any memory issues, but I’d love to have that validated by someone at Cloudflare 😃

0reactions
ashleygwilliamscommented, Dec 6, 2019

i’m going to transfer this issue to the kv-asset-handler repo where the PR to solve this exists!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Videos not working on safari - Apple Support Communities
Whenever I try to play any video on Safari it just shows a blank black screen, ... How could I possibly fix this...
Read more >
How to fix iPad won't Play Videos - Stellar Data Recovery
Methods to fix when iPad won't Play Videos · 1. Low storage space · 2. Unsupported video format · 3. Bad network connection...
Read more >
Videos won't play on iPhone? Here's an easy fix | Documents
Wondering why videos won't play on your iPhone? Chances are that your device doesn't support the file format of the video you want...
Read more >
Videos not playing on IOS Safati - WordPress.org
Hi, This may occur from multiple reasons, you can try doing the following : Make sure the video is on Mute, as some...
Read more >
HTML5 Video autoplay on iPhone - ios - Stack Overflow
I had the same problem - the video not play on iOS. I tried all the code options "playsinline autoplay loop muted".
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found