remotion-dev/remotion

[Idea] Detect/fix font-display: swap #317

sashee posted onGitHub

I've just got bit by the font-display=swap property. It's mentioned in the docs that:

Google Web Fonts by default appends ?display=swap to their URLs. Make sure to remove it to ensure the video renders correctly if you have a slow internet connection.

But it turns out it's not just keeping in mind to remove the query parameter when I copy-paste the font URL as 3rd-party dependencies could also hardcode it in their code (example).

This got me thinking how to solve this automatically.

As the rendering process has access to the network requests the page makes (ref), it could warn if there is a request that goes to the Google Web Fonts URL with ?display=swap. This would be a helpful warning message during the rendering. Maybe it's even possible to do this using a Service Worker in the preview.

But it can go further. The rendering could also check the results of CSS requests and see if there is a font-display: swap in them. This would make it not specific to Google Web Fonts. On the other hand, it might flag false positives.

But it can go further still. I think there is no need for font-display: swap during rendering ever. So the browser could remove that from all CSS responses (maybe even from inline CSS). This would solve this problem for good, and a hidden hardcoded ?display=swap wouldn't result in flickering.


This is a very nice idea! Thanks for explaining it! I totally agree, we should at least put a warning, and actually this technique could also enable other nice DX features! Putting this onto the roadmap with the intent to implement.

posted by JonnyBurger almost 4 years ago

@jonnyburger has funded $50.00 to this issue.


posted by issuehunt-app[bot] almost 4 years ago

@JonnyBurger, I spent many hours investigating this issue today and I have some notes:

It looks like browsers have a Promise-based way to notify when fonts are ready: document.fonts.ready.

<details><summary>Demo (wait until the end)</summary>

https://user-images.githubusercontent.com/13774309/124020618-ca079000-d9ea-11eb-9cd8-b36b4dfe4dd0.mp4

</details>

So I thought about making Puppeteer wait for this to resolve before continuing with the code below in this part of the process.

await page.evaluateHandle('document.fonts.ready');

But then I got stuck in reproducing the font swapping consistently... 😓

Although we can throttle CPU and Network within Puppeteer, I could only reproduce this a couple of times. I tried to reduce concurrency as well but almost always I got a video with the font already loaded.

<details><summary>Demo</summary>

https://user-images.githubusercontent.com/13774309/124021850-5797af80-d9ec-11eb-9314-fb3b0b8690c1.mp4

</details>

I'd like some help to get a stable reproducible scenario to verify if document.fonts.ready solve this behaviour without any overhead (warning the user or hacking the rendering to remove the font swapping).

I've opened a draft PR with some of the changes I did regarding all of the above. If we think we're on a right track, you can assign me the issue. 😄

Please let me know your thoughts or if I missed something, etc.

posted by arthurdenner over 3 years ago

Thanks a lot for digging into this! 😍 that looks awesome!

I have an idea what might be the issue, document.fonts.ready is always truthy because it's a promise. That doesn't mean that the fonts are already loaded necessarily.

See my other comment, maybe it's helpful?

posted by JonnyBurger over 3 years ago

Hey, thank you for the reply and link. I read that article a few days ago, it certainly helped my investigation.

await page.evaluateHandle('document.fonts.ready');

The line of code above seems to work fine from what I've debugged and from the GitHub blog post - they needed a custom solution for images only.

Sorry, I wasn't clear - I was about to go to bed when I wrote the previous comment - but my issue is reproducing the font swap behaviour.

I couldn't get a scenario where the fonts would swap in the middle of the video every time, only a couple of times (and I recorded one of them), even when disabling the cache or throttling the CPU and Network. 😅

If you have a repository or tips on how to get the font swap behaviour every time, we could verify if documents.fonts.ready really solves it.

posted by arthurdenner over 3 years ago

Hey @arthurdenner ,

my 2 cents: you can use request interception in Puppeteer (ref) to stall requests to certain urls. With this, I believe you can postpone requests loading fonts to be able observe the font swap effect.

posted by sashee over 3 years ago

@sashee, your 2 cents were very valuable! Thank you very much!

I tried that approach before but it didn't work. I tried to use a "delay proxy site" (https://deelay.me) and it didn't work.

So I debugged this a lot more today and noticed that I wasn't working on the correct file. I was modifying the process for the evaluation not the composition. 😅

The approach you suggested worked fine in the new file and I was able to reproduce the font swapping many times. 🥳

My draft PR is now updated and has instructions to reproduce it and videos of before and after the proposed fix.

Please have a look at it and let me know your thoughts and findings. I really hope it works for you too! 🙌🏽

posted by arthurdenner over 3 years ago

@jonnyburger has rewarded $45.00 to @arthurdenner. See it on IssueHunt

  • :moneybag: Total deposit: $50.00
  • :tada: Repository reward(0%): $0.00
  • :wrench: Service fee(10%): $5.00
posted by issuehunt-app[bot] over 3 years ago

Fund this Issue

$50.00
Rewarded

Rewarded pull request

Recent activities

arthurdenner was rewarded by jonnyburger for JonnyBurger/remotion# 317
over 3 years ago
arthurdenner submitted an output to  JonnyBurger/ remotion# 317
over 3 years ago