Bluesky Image/Video Download Button

Adds a download button to Bluesky images and videos. Built off coredumperror's script with a few improvements.

< Feedback on Bluesky Image/Video Download Button

Review: Good - script works

§
Posted: 03/12/2024

This does not download the highest picture quality.

URLs that end with @jpeg should be replaced with @png for better quality (never use @webp though, it's awfully compressed).

KanashiiWolfAuthor
§
Posted: 03/12/2024

After using some online tools to compare the images between the one downloaded from the script (below, which uses their API as documented here) and the one downloaded by swapping to @png, I'm getting a 100% match, if you can give me an example, I'd appreciate it.

    function downloadContent(url, data) {
        const urlArray = url.split('/');
        const did = data.isVideo ? urlArray[4] : urlArray[6];
        const cid = data.isVideo ?
            urlArray[5] :
            urlArray[7].split('@')[0];

        fetch(`https://bsky.social/xrpc/com.atproto.sync.getBlob?did=${did}&cid=${cid}`)
            .then(response => {
                if (!response.ok) {
                    throw new Error(`Couldn't retrieve blob! Response: ${response}`);
                }
                return response.blob();
            })
            .then(blob => sendFile(data, blob));
    }
§
Posted: 03/12/2024
Edited: 03/12/2024

I don't think the PNG file can be retrieved from the API.

The trick is to replace `feed_thumbnail` with `feed_fullsize` and the `@jpeg` with `@png` in URLs like:
https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:my4e5afe5eryhrm773tah5pz/bafkreifwt4m3ezp5kxxq62wdgvsdfoynnkuwzu6pp5efkbn7634ap3izyq@jpeg

which gives:

https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:my4e5afe5eryhrm773tah5pz/bafkreifwt4m3ezp5kxxq62wdgvsdfoynnkuwzu6pp5efkbn7634ap3izyq@png

If you compare the two pictures, the PNG is smaller in size compared to the JPEG, and it's also uncompressed, thus it's much better quality (there are no lossy compression artifacts).

It might only work if the original picture was uploaded in PNG format, but I don't know for sure yet. The PNG file might not actually be the original file either, no idea, but it's still better quality than the JPEG.

KanashiiWolfAuthor
§
Posted: 03/12/2024
Edited: 03/12/2024

I get what you're saying, but:

https://bsky.social/xrpc/com.atproto.sync.getBlob?did=did:plc:my4e5afe5eryhrm773tah5pz&cid=bafkreifwt4m3ezp5kxxq62wdgvsdfoynnkuwzu6pp5efkbn7634ap3izyq

is how the API sees it, which is identical in pixel-to-pixel quality to the @png from your link:

https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:my4e5afe5eryhrm773tah5pz/bafkreifwt4m3ezp5kxxq62wdgvsdfoynnkuwzu6pp5efkbn7634ap3izyq@png

However, you are correct that the PNG is smaller, but it won't always be the case:

https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:f4auja6pfrn2fqmbzvlrhymp/bafkreid4eq5vyenfh6uvcwv5mlo45ubjot6ufym7xloqiadpcl2dndpky4@png (1475KB)

https://bsky.social/xrpc/com.atproto.sync.getBlob?did=did:plc:f4auja6pfrn2fqmbzvlrhymp&cid=bafkreid4eq5vyenfh6uvcwv5mlo45ubjot6ufym7xloqiadpcl2dndpky4 (267KB)

and once again, using tools online to compare the PNG to the API gives no pixel difference.

Results Page https://www.img2go.com/result#j=19054f74-4643-41a4-8926-bc67582bd1ef

There's no way for me to determine which will be the smaller filesize nor the original version of the image without downloading both and doing personal inspections. However, all my experiments are showing no introduction of new artifacts when comparing the API to the fullsize PNG so I don't see (at this moment) a reason to replace the current method. I appreciate the dialogue though and would love if we could find a situation where the API clearly gave the inferior quality by introducing artifacting to the image, I would change it on the spot (I've already written it, I just want undeniable proof and I will implement it)!

As a side tangent, bsky isn't really the best location to download from if your major concern is attaining the original quality of the art produced, while it works for disseminating the art into a wider public, you should always check their bio to see if they share a link to their pixiv or another image hosting site. Bsky limits image dimensions to 2000px and there's no guarantee that they're not compressing everything uploaded from the get-go.

§
Posted: 03/12/2024

Right, thanks for providing that example.
The PNG trick that made the file smaller was pure luck in my case, so let's ignore that one. It's a nice optimization trick but it's not what the topic was about, I did not pick a good example, sorry about that.

The PNG is most likely generated on the fly from the original picture then, and if that original file was a JPEG, there is no point in downloading the PNG.

So in conclusion, you're right. The file returned by the API is most likely the best we can get.

I tried uploading a PNG file to Bluesky, but it does not seem to be working at the moment, the resulting picture is all black. Perhaps this is a temporary bug on their end. If it's always been like that, it's safe to assume all files uploaded until now were JPEG, so there is no point trying to get PNG variants indeed.

Also thanks for forking and maintaining this script! ;)

KanashiiWolfAuthor
§
Posted: 03/12/2024

It's not that your example was lacking, it was a good tool to exemplify that there is a PNG difference that exists, but we just don't yet know why it exists. They strip all the transparencies from PNGs regardless of method of downloading the image. I tried converting a PNG into a still-image GIF and it just turns it into an MP4 regardless, so there's a lot of questionable decisions being made by the devs at bsky.

Thank you for making this discussion, because for all I know, you could be entirely correct! You're helping me keep a broader perspective on where to watch for improvements!

Post reply

Sign in to post a reply.