shish/shimmie2

videos timeline cannot be used when using Chrome/Edge with Nice URLs enabled

Opened this issue · 4 comments

Server Software
(You can get all these stats from http://<your site>/system_info)

shimmie: "2.11.0-alpha-20240303-e5471df"
schema: 21
php: "8.2.7"
db: "pgsql PostgreSQL 15.6 on x86_64-pc-linux-musl, compiled by gcc (Alpine 13.2.1_git20231014) 13.2.1 20231014, 64-bit"
os: "Linux 0417ce3dc971 5.10.0-26-amd64 1 SMP Debian 5.10.197-1 (2023-09-29) x86_64"
server: "Unit/1.32.0"

Client Software (please complete the following information)

  • Device: desktop/mobile
  • Browser: [Edge v121, Chrome v120]

What steps trigger this bug

  1. enable Nice URLs
  2. open a video post (tested with mp4 videos)
  3. try to scrub backwards or forwards or jump to any location on the video's timeline

What did you expect to happen?
Be able to jump to any location and to scrub backwards/forwards on video timeline.

What actually happened?
The timeline does not react to input. Trying to e.g. use JavaScript to change the video's currentTime property will reset the video to play from 0.

All of the above is working in Firefox.

This seems to happen because Chromium-based browsers insist on the server responding with the "Accept ranges" header when serving the video element. This and other headers are defined in /core/basepage.php, but do not get sent when Nice URLs are enabled. This affects the following headers when serving video:

  • Accept-Ranges
  • Content-Disposition
  • Content-Range
  • Content-Type

When Nice URLs are disabled, all of the above headers are sent and the video timeline can be used also in Edge or Chrome.

Ergh, Unit doesn't support this ( nginx/unit#1011 ) and the recommendation is to use the application server to serve static files ;(

hm. What confuses me is how the Accepted Range header and others are being sent alright when Nice URLs is disabled - does this mean Unit is being used to serve the media file if Nice URLs are enabled, while PHP is used while Nice URLs are disabled?

Or is URL rewriting used to make Nice URLs work and there may be some rules overwriting or removing the required headers from being sent?

I'm guessing there's no way to have PHP add that header when videos are being served - at least not without losing the efficiency of NGINX there?

does this mean Unit is being used to serve the media file if Nice URLs are enabled, while PHP is used while Nice URLs are disabled

That is correct - by default (niceurls disabled) shimmie does everything by itself, which is flexible but inefficient (thumbnails are the worst case - viewing the post list ends up loading 25 copies of the application in order to serve 25 tiny static images). Niceurls enabled indicates that the web server has been configured to be a bit more helpful and integrate better, in which case we rely on the web server to handle static files. But TIL unit's file-serving code, while much more efficient than PHP, is missing range support D:

alright that is too bad - let's hope they implement it one day but that issue has been open for quite a while :/

Meanwhile, I tried working around this by modifying run.php to add that header to Unit's routes:

    "routes" => [
        [
            "match" => [
                "uri" => "~/_(thumbs|images)/.*"
            ],
            "action" => [
                "share" => [
                    '`/app/data/${uri.replace(/_(thumbs|images)\\/(..)(..)(.*?)\\/.*/, "$1/$2/$3/$2$3$4")}`',
                    '`/app/data/${uri.replace(/_(thumbs|images)\\/(..)(.*?)\\/.*/, "$1/$2/$2$3")}`'
                ],
                "response_headers" => [
                    "Cache-Control" => "public, max-age=31556926",
                    "Accept-Ranges" => "bytes"
                ]
            ]
        ],

From what I've read so far this shouldn't break anything, but this means the header will always be sent when serving any media, including images or thumbnails, but oh well.

With this change the video timeline can be used in Chromium-based browsers now. I just hope not to run into any case where any of the other headers are needed since I would have no idea of how to populate those dynamically :D.