@damus @utxo the webmaster 🧑💻 #asknostr #nostr #damus #blossom #haven Something strange happening with me: if i post videos to my haven blossom server, damus cannot load them on iOS (other clients working fine). But the same video uploaded to my website works fine. Is it a problem with damus? (seems so, since it works in other clients) is it a problem with haven? (also might be, since uploading to an apache webserver works) or is it the blossom implementation used by haven? will send examples as reples.
this one is on my haven/blossom server: https://haven.girino.org/4d32eba13325eed7fd1926c3f9f0d6679da837c0228c8f3accd402790a776312.mp4
It's damus
This one is on my apache server, not on blossom, and should work on damus. https://girino.org/nostr/4d32eba13325eed7fd1926c3f9f0d6679da837c0228c8f3accd402790a776312.mp4
haven request is missing: content-length accept-ranges: bytes it's possible ios video player requires one of these
haven response*
yes I noticed damus doesn't load any blossom video. its easy to blame damus but we use the default ios media player, so unless utxo wants videos to not work on ios at all, I suggest returning these headers and see if it fixes it.
So you walk into a bar, and there is a purple moose drinking water to get to the meadow, and some moose from some other forest walks in. The entanglement explains where there are meese in various continents with most infinite connections. ••.•• Confusion entanglements non infinite life. Animals. 😵 #mainvolume
Or something
Although must be infinite mass to matter 😭
@utxo the webmaster 🧑💻 cc @hzrd149 see blossom config feedback reqd for ios
I meant to say “any haven video” here not blossom
Ok I'll add
https://pkg.go.dev/net/http#ServeContent - this is what you are looking for (it will handle partial byte ranges and all mentioned headers).
but AFAIK, this needs to be done on khatru, because it does not expose the required objects. that's why i involved @fiatjaf in the thread.
Try to replace `io.Copy` with `http.ServeContent` and see what happens (you can fork Khatru and use go to replace khatru dependency in Haven, this is how I tested all of the CORS stuff before)
this worked wonders! I'll keep testing it and submit a pull request by tomorrow. the changes were a little more complex than just adding a call to ServeContent (they always are) but i think i managed to get everything right. see here: https://github.com/fiatjaf/khatru/compare/master...girino:khatru:master (there is still some debug "prints" in there, i'll remove them before the pull request)
Looking good! If you’re open to a small suggestion, and if fiatjaf doesn’t mind introducing some early-stage backwards-incompatible changes to khatru's Blossom’s API, I think you could simplify things by changing the return type here https://github.com/fiatjaf/khatru/blob/76ecf4f7914a93b7ec4f0cc0c823304a7402adab/blossom/server.go#L18 to `io.ReadSeeker`. This would allow you to eliminate the `io.Copy` fallback code and the `Content-Type` handling, as `http.ServeContent` also takes care of that for you. It even handles ETags and cache-related headers, so I’d expect your patch to significantly improve things for all clients—not just iOS. Well done!
#nostrdam was fun. That moment of time when the future happened. @Tanja was there as well, along with @Ian and @nextblockcoffee The butterflies conga. At least the entanglement answer the most common question of how do you know #nostr. https://image.nostr.build/d45e839adc02c507bf50c174677d3c992cce0ac5e46513ea8b1be46dfb878f45.jpg
Unexpected to have the science department to hold the knife Public transport science department of expensive fireworks by the word on the street https://image.nostr.build/e44271c4e0ecd555d2f5307a98fdb8a7b42ab5d511f59eae3863f1a88b18ee0d.jpg
I didn't know IOS required range requests for videos to work but i guess it makes sense right now the blossom spec does not mention anything about content-length or accept-ranges but it might be good to add it, thoughts?
@utxo the webmaster 🧑💻 wdyt
If iOS requires it we basically have no choice
https://github.com/hzrd149/blossom-server/issues/16 @hzrd149 not sure if this is the right repo
I think that by specs he meant this one: https://github.com/hzrd149/blossom But if the reference blossom server is not handling range requests / partial content the issue above is also valid.
fwiw im not sure if it is the issue, its just the biggest thing i saw that was different between the headers of the server responses. Would be good to know which header specifically is the issue, assuming both servers are returning the same data and there isn’t some other subtle issue.
It was indeed the issue, already fixed and tested by Girino and PR submitted to khatru upstream. (Check rest of this thread)
i wouldn't be so bold, since i din't mess directly with the headers. I just used a different API http.ServeContent, that handles the headers for me. It might any other header handled by this API that we were not aware of. We should conduct tests manually setting headers to check which one is the one required by iOS. or simply leave it be, and document that videos might not work in iOS without extra headers, and let the devs fend for themselves.
It’s probably in the apple docs somewhere but im too lazy to find it
https://stackoverflow.com/questions/3397241/does-iphone-ipad-safari-require-accept-ranges-header-for-video
BotGPT: “When dealing with video playback on iOS devices, especially when using third-party video storage servers, it's important to ensure that the server's response headers are properly configured to support smooth streaming and playback. Here are some key HTTP headers and their ranges that you should consider: 1. **Content-Type**: This header indicates the media type of the resource. For video files, common types include: - `video/mp4` for MP4 files - `video/quicktime` for MOV files - `video/x-ms-wmv` for WMV files - `video/webm` for WebM files 2. **Accept-Ranges**: This header should be set to `bytes` to indicate that the server supports range requests. This is crucial for seeking within the video. - Example: `Accept-Ranges: bytes` 3. **Content-Length**: This header specifies the total size of the video file in bytes. It is important for the client to know the size of the file for buffering and playback. - Example: `Content-Length: 12345678` 4. **Content-Range**: This header is used in response to a range request. It indicates the range of bytes being sent in the response and the total size of the file. - Example: `Content-Range: bytes 0-999/12345678` 5. **Cache-Control**: This header can be used to control caching behavior. For video content, you might want to set it to prevent caching or allow it based on your needs. - Example: `Cache-Control: no-cache` or `Cache-Control: public, max-age=3600` 6. **Expires**: This header can be used to specify when the content should be considered stale. It can be set to a future date to allow caching. - Example: `Expires: Wed, 21 Oct 2025 07:28:00 GMT` 7. **Cross-Origin Resource Sharing (CORS)**: If your video is hosted on a different domain, you may need to set CORS headers to allow access from your iOS app. - Example: `Access-Control-Allow-Origin: *` 8. **Content-Disposition**: This header can be used to suggest how the content should be handled (inline or as an attachment). - Example: `Content-Disposition: inline; filename="video.mp4"` ### Example of a Response Header for Video Playback Here’s an example of what the response headers might look like for a video file: ``` HTTP/1.1 206 Partial Content Content-Type: video/mp4 Accept-Ranges: bytes Content-Range: bytes 0-999/12345678 Content-Length: 1000 Cache-Control: no-cache Expires: Wed, 21 Oct 2025 07:28:00 GMT Access-Control-Allow-Origin: * ``` ### Summary To ensure optimal video playback on iOS devices from a third-party video storage server, make sure to implement the above headers correctly. This will help facilitate smooth streaming, seeking, and overall better user experience.”
Partial content goes beyond headers. It requires additional logic to handle the correct ranges, HTTP status codes, and more. The `http.ServeContent` function took care of all this for you. No worries about being "bold" here. I’d much rather have range requests explicitly specified in the Blossom specs (it’s a crucial feature for a media server anyway) than deal with more half-baked, hardcoded headers scattered everywhere. We already have too many incorrect or overly simplified assumptions about how HTTP works baked into most Nostr libraries, clients, and relays. Having something in the standarda is actually the right approach if we want Blossom to succeed.
Github issue for discussing it further https://github.com/hzrd149/blossom/issues/37
maybe an "accept-ranges: none" is enough? will try that later.
It probably uses ranges for incremental downloading if the connection drops
It’s a great video, special case when needing to adapt to the entanglement in question causing meese. https://youtu.be/1WkvomHrfVo?si=YX6tBWwTqpvaxijw
I was looking into the code for haven, and this would probably need to be fixed in khatru itself, somewhere around here: https://github.com/fiatjaf/khatru/blob/master/blossom/handlers.go#L193 So i think we need to involve @fiatjaf here.
Can you try to PR it? Fiatjaf and I don't have iOS it's hard for us to test
@Anthony Accioly , you're better at this than i am. I'll try it tomorrow, but i don't think i know golang enough to deal with it. Do you have an iOS device where you can test this?
I unintentionally forked the conversation above. I don't have an iOS device but happy to help if you get stuck :).
This is such a shameless excuse. You don't need iOS to add a Content-Length header.
But we can't know if this is actually causing the issue on iOS
This works on Damus
Problem solved here @utxo the webmaster 🧑💻.