New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(media): Blurhash #1381
feat(media): Blurhash #1381
Conversation
src/routes/_utils/blurhash.js
Outdated
const pixels = decodeBlurHash(blurhash, 320, 320) | ||
|
||
if (pixels) { | ||
canvas = canvas || document.createElement('canvas') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mastodon renders the canvases directly but I though that it's too much overhead to create and destroy that many canvases so I went with this approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if toBlob()
with a Blob URL may actually be more performant here than a data URL. I'll play around with it. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, so the problem with toBlob()
is it's asynchronous, meaning that there might be a flash of unhidden sensistive media unless we're careful about doing the blurhashing in advance. I might keep noodling on this after merging the PR.
@@ -48,6 +48,7 @@ | |||
"@webcomponents/custom-elements": "^1.2.4", | |||
"babel-loader": "^8.0.6", | |||
"babel-plugin-transform-react-remove-prop-types": "^0.4.24", | |||
"blurhash": "^1.1.3", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could try https://github.com/fpapado/blurhash-rust-wasm if performance turns out to be an issue.
import { decode as decodeBlurHash } from 'blurhash' | ||
import { mark, stop } from './marks' | ||
|
||
const RESOLUTION = 32 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could maybe lower this based on some heuristics (e.g. navigator.hardwareConcurrency
)? Setting it to 1 will basically extract the average color, so maybe we can do that initially and repeat with 32 inside a requestIdleCallback
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what the limiting factor is for blurhash, but yeah for now a hard-coded value is probably fine.
Thanks very much for this PR!! I made some minor refactoring changes. At this point, my only major concerns are:
For now I'm mostly concerned about # 1; maybe it's time for me to retire the "show large inline images system." Or we could implement blurhash for it. |
Created a poll to see if anyone is using this setting: https://mastodon.technology/@pinafore/102593964013067092 |
Awesome! In that case I'd say remaining tasks are:
|
Can't seem to get |
Pushed a commit where the computations are moved to a Web Worker:
Some things still need to be addresses though:
|
@@ -141,6 +166,7 @@ | |||
}, | |||
data: () => ({ | |||
oneTransparentPixel: ONE_TRANSPARENT_PIXEL, | |||
decodedBlurhash: ONE_TRANSPARENT_PIXEL, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ONE_TRANSPARENT_PIXEL
is used while the async computation is pending.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good workaround!
@@ -0,0 +1,49 @@ | |||
import BlurhashWorker from 'worker-loader!../_workers/blurhash' // eslint-disable-line |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I couldn't get worker-loader
working when added to client.config.js
for some reason. Standard complains about the inline use of the loader, disabled it for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fine; I don't really care whether the worker-loader
is referenced in the Webpack config or in the import.
Added caching, but we are still leaking memory due to never calling |
Throws exception which prevents the image from loading.
Fantastic work, this looks great to me. I only have some minor issues remaining:
Both of these things can be fixed later, though; overall I think this is a fantastic PR and we should just get it in master and fix the minor things later. Thanks for the excellent work!! |
Todo:
Closes #1179.