#react native expo does not play same sample video from FastAPI

50 messages · Page 1 of 1 (latest)

bitter lavaBOT
#

Project ID: N/A

hollow cloak
#

so that video with the link you gave doesnt work for you? is that correct? because it plays for me in both chrome and firefox

spring cove
#

It works in browser. I downloaded it from Amazon s3 just to test. It works in browsers. It works on react native when on S3 but not from fastapi.

#

Same video

hollow cloak
#

can you send the link to the video thats served from fastapi

spring cove
#

It’s on top. You said you could play it in browser

#

This is original sample that plays

#

And this one does not play on my react native app

hollow cloak
#

are there any errors? the video works and can be streamed in the browser, so theres no issues there with fastapi or railway

spring cove
#

No errors except favicon error on browser

#

Both curls return 200

#

It must be sth in react

hollow cloak
#

theres not too much i can help you with if theres no errors, at the very least its not an issue with your code or railway

#

it must be a client side issue

spring cove
#

I think so. Meaning react.

#

But funny thing is only uri is different on react

#

I mean different for s3 or here

hollow cloak
#

has anyone else experienced the same issues with react native? since this isnt an issue with your code or railway

spring cove
#

I saw some posts on stack overflow saying same video would not play but no answers or solutions. I’ll keep looking

#

Like you said nothing to do w/o errors. Thanks again 🙂

hollow cloak
#

no problem!

spring cove
#

Here is something weirder.
It plays on Android simulator from FastAPI. It plays on both when url is changed to S3 ( same video )

hollow cloak
#

I say blame apple

spring cove
#

🙂 🙂 yeah 🙂 🙂

hollow cloak
#

classic apple

spring cove
#

I just read some place 'content-type': 'video/mp4', needs to be set for apple. I will look into this to see If I can do that from FastAPI but then I remembered the headers which I posted above. Both headers declare the type

hollow cloak
#

indeed they do

spring cove
#

It plays on safari but gives some kind of error. Failed to play the resource, plugin handled the load

hollow cloak
#

now what the heck is that supposed to mean

spring cove
#

They say needs to be streaming response in chunks of bytes. I'll see if there is a way to do that in fastapi

hollow cloak
#

interesting

spring cove
#

Something like this may be. If I find a solution, I'll write here so others can see. It is a weird problem

hollow cloak
#

yeah that looks like it would do what you want, then you can use that route for the video folder instead of a static server that you currently use

spring cove
#

Right. Thanks. It turns out tiangolo talks about this.

hollow cloak
#

hmmm

spring cove
#

Got it working at last 🙂 I have not deployed it yet since this time Android would not play the video if you can believe it 🙂 I lost a couple of hours debugging and remembered Android never played videos when tested locally :)))) It has to be on the server. Because Android thinks 127.0.0.1 or localhost is inside the phone :))) So I lost some hours for nothing 🙂 I knew this but just did not occur to me :))

#

part 1

import os
from typing import BinaryIO

from fastapi import FastAPI, HTTPException, Request, status
from fastapi.responses import StreamingResponse


def send_bytes_range_requests(
    file_obj: BinaryIO, start: int, end: int, chunk_size: int = 10_000
):
    """Send a file in chunks using Range Requests specification RFC7233

    `start` and `end` parameters are inclusive due to specification
    """
    with file_obj as f:
        f.seek(start)
        while (pos := f.tell()) <= end:
            read_size = min(chunk_size, end + 1 - pos)
            yield f.read(read_size)


def _get_range_header(range_header: str, file_size: int) -> tuple[int, int]:
    def _invalid_range():
        return HTTPException(
            status.HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE,
            detail=f"Invalid request range (Range:{range_header!r})",
        )

    try:
        h = range_header.replace("bytes=", "").split("-")
        start = int(h[0]) if h[0] != "" else 0
        end = int(h[1]) if h[1] != "" else file_size - 1
    except ValueError:
        raise _invalid_range()

    if start > end or start < 0 or end > file_size - 1:
        raise _invalid_range()
    return start, end
#

part 2:


def range_requests_response(
    request: Request, file_path: str, content_type: str
):
    """Returns StreamingResponse using Range Requests of a given file"""

    file_size = os.stat(file_path).st_size
    range_header = request.headers.get("range")

    headers = {
        "content-type": content_type,
        "accept-ranges": "bytes",
        "content-encoding": "identity",
        "content-length": str(file_size),
        "access-control-expose-headers": (
            "content-type, accept-ranges, content-length, "
            "content-range, content-encoding"
        ),
    }
    start = 0
    end = file_size - 1
    status_code = status.HTTP_200_OK

    if range_header is not None:
        start, end = _get_range_header(range_header, file_size)
        size = end - start + 1
        headers["content-length"] = str(size)
        headers["content-range"] = f"bytes {start}-{end}/{file_size}"
        status_code = status.HTTP_206_PARTIAL_CONTENT

    return StreamingResponse(
        send_bytes_range_requests(open(file_path, mode="rb"), start, end),
        headers=headers,
        status_code=status_code,
    )


app = FastAPI()


@app.get("/video")
def get_video(request: Request):
    return range_requests_response(
        request, file_path="path_to_my_video.mp4", content_type="video/mp4"
    )
hollow cloak
#

oh wow, that's a lot of code, at this point I would have setup an actual file server with caddy or something

spring cove
#

🙂 yeah, true 🙂

hollow cloak
#

well now I got myself thinking, will caddy do video streaming by default

spring cove
#

Yes it does

#

Not only video of course. Any type of large file 🙂

hollow cloak
#

well now so does fastapi

spring cove
#

Well, this code that I posted uses some of the FastAPI libraries. Tiangolo comments on the github repo.

#

However, some of the streaming is handled by servers like S3 for instance. I wonder what happens then. Who decides what the chunk-size will be for instance. Oh well 🙂 It works I'm happy 🙂