Episode Transcript
Transcripts are displayed as originally observed. Some content, including advertisements may have changed.
Use Ctrl + F to search
0:00
Ooh, welcome to syntax on this Monday, hasty
0:03
treat. We're going to be once again, talking
0:05
about the thing that we all hold so
0:07
dearly. In fact, we hold it for a
0:09
long time. Sometimes we hold it for days
0:12
and days. I'm talking about caching. We're going
0:14
to be talking about caching, but not necessarily
0:16
in the ways that we've talked about it
0:18
before. We're going to be talking about the
0:20
cache API, which many people think of as
0:23
being part of service workers, but we're going
0:25
to be talking about how we used it
0:27
to build a Netflix style save for offline
0:29
for the application for
0:31
podcast episodes on our syntax site. My
0:34
name is Scott Tolinsky. I'm a developer
0:36
from Denver and with me as always
0:38
is Wes boss. Hey,
0:40
I am really excited about this because
0:43
I did not realize that this was the
0:45
API that you needed to, to
0:48
store stuff locally, um, in the browser.
0:50
I always thought it was like file system APIs
0:53
or index DB. And it turns out
0:55
that there is a really nice cache API.
0:57
That's not just service worker. I've used it
0:59
plenty of times in service workers, but not
1:01
for storing data in the browser and
1:03
I've always wondered myself, like I would love to be
1:06
able to. For
1:08
my courses, like save them in the browser,
1:10
so people can watch them, but still get
1:12
the whole streaming experience. You know? Yeah. I
1:14
know the solutions I thought of for that
1:16
at some point, because I thought about the
1:18
same thing when I was doing level up
1:20
tutorials was, I guess I'm
1:22
going to have to make an electron app,
1:24
right? Making a desktop app and then therefore
1:26
they could download the course and then have
1:28
it be easily work with the file system
1:30
that way because the browser file system, if,
1:32
if we haven't taken a look at
1:34
that yet, in fact, maybe I should even pull that up here before
1:37
we even get too deep into this, if
1:39
you are listening on audio, we'll be showing some
1:41
stuff on video here. I know, I know I've
1:44
said that a couple of times here, but I'll
1:46
be pulling up API docs, I'll be showing some
1:48
code. We're going to make the experience of the
1:50
episode work just fine with audio as well. But
1:52
I will be showing some things like this,
1:54
like the file system API. And
1:57
you can see what the file system API browser.
2:00
is not yet here. It works with Safari,
2:02
it works with Chrome, it works with Edge.
2:04
It does not work with Firefox fully. Now,
2:07
this is going to be the type of thing that's potentially
2:10
going to throw an error in your system if you're
2:13
trying to load up the file system API and
2:15
it doesn't exist and you don't have permissions for
2:18
it. For something like that, you might want a
2:20
tool like Sentry at sentry.io/syntax. Sign up and get
2:22
two months for free and it'll track and log
2:24
all of the errors in your application and that's
2:26
going to be really handy if you're working with
2:28
things like a cache, right? You don't know what
2:30
you don't know if you're trying to save things.
2:33
So, why not use the file
2:35
system API for storing this kind of thing? One,
2:37
it doesn't work on every browser. Two, you do
2:40
have to get permissions and how,
2:42
like, you click a thing to
2:45
access the file system API.
2:47
In fact, I did a whole course using
2:49
the file system API and it
2:51
pops up saying like, hey, the browser wants to
2:53
access your local files. I think they can bring
2:55
some people out. It's kind of spooky when it
2:57
happens. It'll freak me out, yeah. So,
3:00
you know, I think there is some reason there.
3:02
I wanted this to just work transparently. Like, you
3:04
hit a button, it saves to
3:06
your system, that's it, right? So,
3:09
that's why I reached for the cache
3:11
API which is, like you mentioned, you
3:13
mentioned it being related to service workers.
3:15
It's a part of the service worker
3:17
API and I think because of that,
3:19
people don't realize you don't have to
3:21
use it within service workers. And in
3:23
fact, somewhere in this
3:25
mess on the MDN docs of paragraphs, it
3:27
says, hey, just because this is a part
3:30
of the service worker API
3:32
does not mean you need to use it
3:34
in service workers itself. It does need to
3:36
be in a secure context, HTTPS, all that
3:38
stuff. Not really super
3:40
surprising there. But, hey,
3:42
man, what is the cache API? It's basically
3:44
a way for you to access and
3:47
cache things in a request
3:49
response way without
3:51
having to do it via the
3:54
browser cache or caching headers. You're
3:56
essentially creating your own cache
3:58
response directly inside. in the browser. And
4:01
it's really pretty simple. So
4:03
we're going to be diving into one, how we
4:06
pulled off, what we pulled off on the
4:08
syntax site, maybe some gotchas. And then we're
4:10
going to be talking even further about
4:13
persistent storage and sizes of storage
4:15
and those types of things. So
4:18
first and foremost, like I said, cache API, you
4:21
could do a lot with this stuff. You can
4:23
put anything in here. There is some caveats
4:26
there in terms of size. So
4:29
Chrome. Chrome is probably the best for this,
4:31
because Chrome lets you store a percentage,
4:34
typically 6% to 10% of
4:37
the device's free space, meaning that if
4:39
your device has 100 gigabytes
4:42
free, you could store anywhere from 6%
4:44
to 10 gigabytes, which
4:46
is kind of wild compared to when you
4:48
see some of the limits of some of
4:50
these other ones, where Firefox has a global
4:52
limit of 2 gigabytes for all storage APIs
4:55
combined. This is cache storage. It's any
4:57
of the storage APIs on your browser.
5:00
Yeah, because there's lots of ways to
5:03
store data in the browser. You have local
5:05
storage. You have index DB. You have one
5:07
of the other ones. I just
5:09
sent you a whole list. Is cookies coming from that?
5:12
Probably not. Local storage, cache API,
5:15
index DB, service worker, and file
5:17
system. So you talked about the
5:19
file system API. We're
5:21
talking about the cache API here. Index DB
5:23
is kind of like local storage, but it's
5:25
a bit more flexible for doing
5:27
full-blown database stuff. And then local storage
5:29
is just a nice key value store.
5:31
What I am curious about this cache
5:34
API is that you said
5:36
it's based on request and response, meaning
5:38
that those are web requests and web
5:41
response. And that's generally the
5:43
way that works with a service worker is that
5:46
when the browser requests like a CSS
5:48
file, you can write a service worker to
5:50
jump in the middle there. And then you
5:53
can say, oh, I've already stored this and
5:55
sent it on back because it's in the cache API.
5:57
But when you're not in a service worker,
6:00
Service Worker that's primarily a fetch request,
6:02
right? Mm-hmm. The thing you need to
6:04
talk about this is that it is
6:07
essentially the same API that you
6:09
use with caching headers, right? You're
6:11
caching things Like normal
6:13
it goes into the the browser cache and
6:15
that is a request response as
6:18
well Right you cache a font or you recr
6:20
at what you cache an image You
6:22
pop open your network tab you see that
6:24
being loaded directly from the cache But it's
6:27
not like it's not like a
6:29
key value store. It's the request and response It
6:31
just happens transparently behind the scenes What this API
6:33
allows you to do is just step in and
6:36
store anything that you want in
6:38
that same caching mechanism Which
6:40
which is thumbs and handy for all kinds of things You
6:43
might be wondering why we don't just cache it
6:45
via HTTP caching I'll tell talk a little bit
6:47
about that but before we get off that Safari
6:49
only has a limit of 500 megabits Megabytes
6:53
I say bits 500
6:56
megabytes per domain and
6:58
if it exceeds that limit Safari Will
7:00
start removing items from the cache to make space
7:03
for new data Which
7:05
is one of the reasons why tools like
7:07
what Riverside that we used for recording You
7:09
can only use it on Chrome because simply
7:11
recording that much video Is
7:14
not gonna work in Firefox or Safari
7:16
because you're gonna hit those limits Probably
7:20
while you're recording which that's no good,
7:22
right? Yeah, I was just just looking at
7:25
I'm in the dev tools right now
7:27
for Riverside as we're recording this and
7:29
they are sticking it in Index
7:33
DB. Yeah, and you can see the
7:35
little chunks like so
7:37
there's an API in the browser called
7:40
media recorder Not sure if they're
7:42
using media record or not But the get user media
7:44
will give you chunks of the users video and you
7:46
can put those into the
7:48
browser storage so that you can upload
7:50
them as you have As
7:53
you have space to do so and I was
7:55
always curious what that looks like and I guess
7:57
the reason why they're using Index DB here instead
8:00
of the cache API is because like
8:02
you said, cache API is only for requests
8:05
in response, right? It's not for, oh,
8:09
I made an image in the browser, or
8:11
I have this canvas element that I want to
8:13
be able to persist offline
8:15
and when I refresh, if it's not actually
8:17
a request to a server,
8:20
the cache API is not for that, right? Yes,
8:23
yeah, and it's, I
8:25
think, I wonder if I could have just
8:27
done this in IndexedDB as well. Honestly, I
8:29
don't know, but I think this was
8:31
the best approach for me and I'll talk a little bit about
8:33
why. I think so because at the end of the day, the
8:37
MP3 for the show is a request, right?
8:39
So it makes sense that you would request,
8:41
you would save it. Yeah, although
8:43
the way I am accessing it, I kind of am
8:45
accessing it like a key value store. Let's
8:48
talk real quick about eviction, that is
8:50
when the data is gone because you
8:53
cannot promise that the data will be
8:55
there forever. We'll talk
8:57
about persistence in just a second,
8:59
but eviction is when,
9:02
at some point, your hard drive is going to get
9:04
full. Between all
9:07
of the origins, which is like a domain
9:09
name on a browser, you're going to be
9:11
using too much of the space and there's
9:13
only so much that Chrome can be
9:16
allowed to use on your user's computer. And
9:19
when you get close to that limit, the
9:21
browser will just purge it for
9:23
you. So I always like to think of
9:25
these caches as unfortunately
9:27
you can keep
9:30
them there for fairly long and it
9:32
works fairly well. Like we use Riverside
9:34
and I don't think ever we've lost
9:36
a recording, maybe once, but
9:40
at a certain point, the browser will purge it
9:42
and you cannot guarantee that it
9:44
will be there forever. Yeah,
9:46
I like to think of these things as like
9:49
questionable storage. Not that it's questionable if it
9:51
will work, but questionable if it will be
9:54
there, right? You couldn't put things
9:56
in here, but you can't always
9:58
assume that it's going to be there. because
10:00
again, because of storage limits, how
10:03
the different browsers work or time or any of
10:05
that, different maybe you open it up on one
10:07
browser profile in another, so you can't always rely.
10:09
You kind of have to take it as like,
10:11
hey, I'm checking to make sure that the cache
10:13
exists first before doing anything. So
10:16
how exactly are we using it and what are
10:18
we using it for? I mentioned a little bit
10:20
about this. I'm gonna show a quick demo here.
10:22
I have the code open, I have a website
10:25
open if you're watching on YouTube, if you're watching
10:27
on your podcast player. If not, I'll describe it
10:29
basically, and I'm gonna preface
10:31
this, this is still in dev. This is
10:33
a, the interface is not complete for this
10:35
yet. So the way this works is
10:38
that I have a little pin here in the
10:40
player, and if I click the pin, it's
10:43
downloading the MP3 right now, and it's
10:45
downloading it and storing it as
10:48
a blob. When it's completed, the pin kind
10:50
of goes straight up and down, again, UI
10:52
is still being worked on here. But
10:54
one thing that you'll notice happened is
10:57
in my dev tools over here, which
10:59
is in dev tools application cache storage.
11:02
You'll see I have an MP3 cache here, and
11:05
now right over here, since that is
11:07
completed, I have an MP3 cache
11:09
where the, essentially the name of
11:12
it is the request URL. So
11:15
just syntax/and then an MP3. I
11:18
chose this URL as,
11:20
a URL that's not going to
11:22
be hit in the site necessarily.
11:25
That's not too important. Either way, you can see
11:27
that, you can see when it was stored, the
11:29
size of it, the response type,
11:31
and if I click on it, yeah,
11:34
there's no preview, but you do get the
11:36
headers and stuff here. So now, if I
11:39
were to go and play this file, if
11:41
I head to my network and I click
11:43
play episode, you can see
11:45
that, where did that go? Where's the
11:47
blob? Okay, so
11:50
I filtered by media, and you can see
11:52
that instead of trying to load this from
11:54
Libsyn, which is where we host our MP3
11:56
files, you can see it's actually loading it
11:58
directly from local host. as a blob
12:00
here. So you can tell size
12:03
is zero bytes because it's
12:05
saved in storage. You didn't have to
12:07
download anything from the internet. So therefore,
12:09
this is now officially loading this file
12:11
from the local storage, not local storage,
12:14
but from my caching API as a
12:16
blob. So how do we
12:18
do this in code? Well, it's actually
12:20
pretty simple. Okay. So when we go
12:22
to save something offline, the first thing
12:24
we do is we fetch the MP3
12:26
as we normally would. And when that
12:29
comes back as a response, we grab
12:31
the blob from it. So
12:33
we don't grab JSON, whatever, it's an MP3,
12:35
right? So we grab the blob. Then
12:38
with that blob, what we're able
12:40
to do is create a new
12:42
response. Now I created a new
12:44
response specifically to attach not
12:46
only like content length here, but also metadata
12:49
here. For some reason, I don't know, I
12:51
don't know if this is maybe you can
12:53
tell me why West when I was doing
12:55
this without adding metadata in creating a new
12:57
response and just using the response from the
13:00
initial fetch, the content length
13:02
was zero for some reason, I had to
13:04
do this manually. I don't, I'm not exactly
13:06
sure why. Oh, that's,
13:10
it's, it's probably because it
13:12
was pulling it from your
13:15
browser's cache initially. Yeah, it's interesting.
13:17
I'm not quite sure why the whole
13:19
response and like streaming thing is really funky.
13:21
I was doing that with the syntax
13:23
website as well where I had to like,
13:26
I was trying to modify a response
13:28
and node was not letting me because
13:30
I'm trying to like modify a header.
13:32
So essentially had to like clone
13:35
the response and then loop over every
13:37
single header and add it in manually.
13:39
Yep. Because it was, it was kind
13:42
of funky. Yeah. So I had to
13:44
create a new response and I did
13:46
so using the blob, I made it
13:49
a content type of audio and MPEG
13:51
again, set the content links myself and
13:53
then the metadata header. What I did
13:55
is I JSON stringified the entire object
13:58
of the show data because What
14:00
we do when we have the syntax player
14:02
and you could click play it doesn't just
14:04
load the mp3 file It has the
14:06
title it has Link
14:08
to the episode it has like share stuff it
14:10
has a lot of information there But
14:13
if you're just doing a request and response to save
14:15
an mp3 And if I
14:17
was going to just cache that mp3 response
14:19
without the metadata It wouldn't
14:21
have any of that and then you'd click play
14:23
and yeah, you'd get the audio, but you wouldn't
14:26
get all the other stuff So I added the
14:28
metadata header I used the JSON stringify through all
14:30
the show information in there So that way when
14:32
we do load from cache we can retrieve that
14:35
information and load it up like normal So
14:37
to actually do the caching bit since I've
14:39
just created the response All we
14:41
did is we do caches, which is a
14:43
global dot open and then you give it
14:46
a name You'll notice mp3 cache
14:48
was the exact same name that we
14:50
saw in The browser
14:52
dev tools when I looked at my
14:54
application cache right here It's the name
14:56
that you're giving to this bucket So
14:59
by giving your information or your
15:01
cache a name you're essentially making
15:04
a bucket So once
15:06
the cache is open it returns a promise so
15:08
I do a then and then I
15:10
can do cache dot put Where I
15:12
then give it a URL which is essentially
15:14
the key of a key value and the
15:16
response which is essentially the value of the
15:18
key value even though it is a Request
15:21
and response at the URL and a
15:23
response not a request so to say
15:25
but a URL and a response That's
15:28
it. That's really it. I can
15:30
then uh, if if you do cache
15:32
dot put there's no async response
15:34
there anything like that You can just be assured
15:36
that it's in there which is neat It
15:39
works really well One thing that
15:41
I had a little bit of trouble trying
15:43
to do that. I would like to try
15:45
to do again Wes was yeah streaming this
15:48
so that way I could get like a progress of how
15:51
Like where I'm at in the downloading
15:53
Oh, yeah process because you can do
15:55
that and I had it working
15:57
to a degree, but I was still kind
15:59
of new to work I was doing. So I'd like to
16:01
try to get now that I have like a fully working
16:04
implementation. I like paired it back
16:06
a bit. You know when you like work on something really
16:09
foreign to you that you haven't done before? You try to do
16:11
a lot of stuff and you're like, let me pull this back
16:13
a little bit to the bare bones so I can get it
16:15
working. So that's where I'm at right now. Okay,
16:18
so this is the whole
16:20
bit for saving it in the cash. Once you do
16:22
this, whatever you're trying to save into the cash you
16:24
open, you put it in the cash. How
16:27
do you get something from the cash manually
16:29
instead of like having it be the browser's
16:31
request for that thing? Well, I'll show you
16:33
that now. It's within the player
16:36
state here. So we wanted to
16:38
have this work very transparently where
16:42
the user is not going to necessarily know if
16:44
they're playing from local or not. So I wanted
16:46
it to be a part of the normal play
16:49
flow. And the normal play flow again, as you
16:51
click play, it loads up the data, it loads
16:53
up the mp3, it saves it all to a
16:55
svelte writable, and then it opens up the player.
16:57
We have a big old state object here. This
16:59
might be the largest state object I've ever written
17:01
in svelte. So how
17:03
do we load it from cash? The first
17:06
thing we do is we open our cash
17:08
of the same name. So mp3 cash returns
17:10
a promise, you await that, then you have
17:12
access to your actual cash. From there, all
17:15
you have to do is a datmatch with the
17:17
string of the path, and it will give you
17:19
a response. That's a normal response. With
17:22
that normal response, what
17:24
I did is I first got the
17:26
metadata headers, I parsed it as JSON, and
17:28
then I essentially returned it as part of
17:31
the data. And then I
17:33
replaced the URL of the data
17:35
that the player is typically looking for
17:37
with a URL created from the blob.
17:39
You can do that with URL create
17:42
object URL pass in the blob, that
17:44
gives you a blob URL. Guess
17:47
what? An audio player, you
17:49
might not know this, you might. An audio player does
17:51
not care if it's a .mp3
17:53
URL or a blob URL, it will
17:55
play the audio as long as it's
17:57
valid. So that's pretty much it. That's
18:00
the whole process. So when you click play it
18:02
really quickly checks to make sure that something is
18:05
in cash If it's not in cash gets out
18:07
and plays a normal one if it's in cash
18:10
Loads it up Makes it into
18:12
a blob URL Plays it
18:14
in the audio player. That's awesome
18:16
I was just looking up your streaming
18:19
thing that you were asking about
18:21
and I remembered that we did a show on
18:23
on streaming and When
18:27
you want to both use a stream for
18:29
something like save it to the cash and
18:32
View the progress you can't do two of those
18:34
things at once, right? You're either you're they're saving
18:36
it or you're viewing the the actual progress if
18:39
you do want to see both of them You
18:41
have to use the dot T method and
18:43
that will basically T
18:46
split it split the stream and one of
18:48
them you can create a reader that will
18:50
watch the progress and then the other One
18:52
you can throw you could
18:54
probably just pass directly into the
18:57
cache API Although adding
19:00
that metadata it might get a little bit
19:02
angry that you're trying to modify the headers
19:05
Yeah, before you put it in that's probably the issue you
19:08
had The metadata piece was interesting
19:10
because I did think like all right. Here's another
19:12
way I could do the metadata. I could toss
19:14
it all in local
19:16
storage and Just with like
19:19
a key of the same key as the cache
19:21
and then when I'm loading up the URL I
19:23
just love that that's very valid. I
19:25
think I could have done that as well I think
19:27
this for me was just like alright, I'll put it
19:30
all in one spot No, BZ, so maybe alternate methods
19:32
there you could do but as you can see I
19:34
can store a couple of these boom It loads pretty
19:36
quick. I got faster in it and every time you
19:38
save one here another one pops in Oh,
19:42
I won. What's that issue? You just got
19:44
I think yeah, what related failed the touch
19:46
mp3 Okay,
19:49
something might be wrong with that mp3 itself. Oh
19:53
I'm on a local build of the site here,
19:55
so I'm not guaranteed. Oh,
19:57
wow another one failed to construct
19:59
response contains an
20:02
ISO. It contains non-ISO code point. Whoa.
20:06
Alright, I got some googling to do.
20:08
Like I said, this is still in my development branch. But
20:10
for generally, it's working. At least the
20:12
first two, it works. So
20:14
I got some googling to do about whatever this
20:17
ISO code point is. I'm
20:19
wondering if it has something to do with the file name. I
20:21
don't know. Let's try this one. This
20:23
is a pretty generic file. Yeah,
20:25
this one's working. There we go. It's
20:28
probably something in the show notes
20:31
that is not
20:33
a... Stringify incorrectly. Okay.
20:36
Yeah. You're doing JSON.stringify of the
20:38
show and there's probably something in
20:40
there. And if you're trying to
20:42
set that to a header, you're
20:44
trying to stick the entire show
20:46
into a header as storage, there's probably
20:48
a weird character in there that it's
20:50
not okay with. Well, here's what I
20:53
should do then, Wes. I should remove
20:55
the show notes because we don't need
20:57
the show notes for the player. We
21:01
really just need things like the show title
21:03
and some metadata there. We don't
21:05
need the show notes saved in there. So I got
21:07
some work to do, so to say. Yeah,
21:10
but even then, if somebody's
21:12
name has an accented character in
21:14
it, are you going to hit that? So
21:17
I'm trying to look at the
21:19
show notes, what it could
21:21
possibly be. Well, these two, let's
21:23
see, this one has a colon and this one has
21:25
an ampersand. I
21:28
think a lot of them have colons and I don't think
21:30
the colon's the problem. So you're right, I bet it's something
21:32
in the show notes itself. Mm-hmm. You
21:35
can encode it, but then you got all those problems
21:37
as well. Yep. So
21:40
bugs to work out, bugs to work out, but
21:42
for the most part, I got four here saving
21:44
and it's working. You'll be able to very soon
21:46
and I'm going to say by the time you're
21:48
listening to this episode, this interface will be tweaked
21:50
and this will be available for you. But you'll
21:52
be able to store this files locally on your
21:54
computer to play offline or your phone or whatever.
21:56
What about if we had something where you went
21:58
to the shows a filter for
22:01
offline saved. Are you able to
22:03
pull out and loop over
22:05
and show those? Or how does that work?
22:07
Let's check the cache API.
22:10
I would imagine you do keys here. I'm
22:12
not positive. I have not thought about that. But
22:15
keys, yeah, you open and you get the
22:17
keys. Hey, bingo bango, Wes, that's it. Yeah,
22:20
nice. Yeah, so we'll be able to
22:23
do that for sure. Another thing I'm going
22:25
to be working on in the same regard is queuing.
22:28
So if you add an episode to the queue,
22:30
I'm going to have it automatically saved to your
22:32
cache. So that way,
22:35
it's like preloading essentially
22:37
for MP3 files. Pretty neat. Awesome.
22:40
One last thing we want to talk about
22:42
is just persistent storage. I
22:44
was always curious about this as to
22:46
when does it get sort of pushed
22:48
out. When we talked about the browser,
22:51
once it gets full, it starts to sort of
22:53
purge. And I found some interesting stuff
22:55
online about this. I'm just going to read through it.
22:58
Each origin gets a higher
23:00
storage limit. By default, the browser will
23:02
evict data by origin, which is a
23:05
domain name. When
23:07
the total usage of all origins is
23:09
bigger than a certain value, the overall
23:11
quota is calculated based on disk space.
23:14
So again, it says, all right, well,
23:16
now Chrome is taking too much of disk space.
23:19
What do I do about that? However,
23:22
at that point, the browser
23:24
says, all right, what do I
23:27
delete? Do I just start deleting
23:29
random stuff? Because some of it will be, yeah, you cache
23:31
a CSS file. It's
23:34
fine. We'll just go download that again. And some of
23:36
it will be more important stuff.
23:38
Like, oh, yeah, I
23:41
saved a recording that hasn't uploaded to the
23:43
cloud yet. And the only place it exists
23:45
is in the browser cache right
23:48
now. So that's pretty important, right? So
23:50
there is an API called navigator.storage.
23:52
It is the API that will allow
23:55
you to see how much
23:57
space is available for you to store stuff.
24:00
navigator.storage.persist is
24:03
the API that will... it used
24:06
to pop up a thing and says, hey, can
24:08
we store stuff in Chrome? And now
24:11
it's just based on flags,
24:13
like how often you visited the website,
24:16
if you've bookmarked it, there's all these
24:18
things. Kind of the same idea of
24:20
when you want to autoplay video. You're
24:23
not allowed to autoplay video unless the
24:25
user has interacted with the website a whole bunch... there's
24:27
a whole bunch of stuff
24:30
that goes into calculating the score
24:33
of a website. So I
24:35
had... now you can just
24:38
say navigator.storage.persist and it's kind
24:40
of like a pretty please, can
24:43
we have elevated storage?
24:45
Like, don't delete us
24:47
first, please. It doesn't pop anything open
24:50
and it simply was returned true or
24:52
false. So I ran it on Chrome
24:54
on Riverside and it returned true. Why?
24:57
Because I'm here often, I spend a lot
24:59
of time on this website, I interact with
25:01
the website, I bookmarked it, and
25:03
then I tried it on a website I've never been
25:05
to and it obviously says no automatically.
25:07
So I don't know what those flags
25:10
are by browser. I think it's up
25:12
to the browser to decide what
25:15
is important and what is not. But
25:17
I thought that was kind of interesting. If
25:20
that feels mysterious, let me tell you, as
25:22
somebody who's had to maintain an
25:24
autoplay feature on a
25:27
website, man, that
25:29
is one annoying system
25:32
to work into because you'll think
25:34
that you have it working, it works for you,
25:36
it works for most people and then you'll get
25:38
a bit of air. Autoplay does not do anything.
25:40
I'm like, okay, great. How am I supposed
25:42
to debug this when it's
25:44
not like it's throwing an air or anything?
25:46
It could just be that they
25:49
have not interacted with the site enough.
25:51
The one thing is that the user has
25:53
to interact with the site before autoplay
25:56
works. I wonder, I wonder
25:59
how much Google, I'm
26:01
not trying to do any conspiracy thinking
26:03
here, but YouTube has no problems with
26:05
autoplay. Is that
26:08
because YouTube and Chrome are owned by the same
26:10
company? I have no idea. No, you can look
26:12
it up. It's called MediaScore. Let me just find
26:14
it. How do you look it up? All right.
26:16
So I'm in Chrome/or
26:19
colon slash slash media
26:21
dash engagement. And
26:23
this will actually give you
26:25
the information about
26:27
how much your user has interacted with it
26:29
and it will give you whether
26:31
it is a high media engagement score
26:34
or not. And if
26:36
you have a high media engagement score,
26:38
that is one of the ways that
26:40
you are allowed to autoplay videos. So
26:42
look at this YouTube 16 sessions, six
26:45
of them. I actually played something
26:47
last time I played something was
26:50
January 1st because I don't use Chrome
26:53
for anything other than recording this podcast.
26:56
But it is a high media engagement score. And
26:59
then all of these other websites
27:02
here are just like
27:05
domains or origins that I
27:07
have interacted with. And
27:09
it has a low media engagement score. I'm kind
27:11
of curious if I look
27:14
it up. I switched to Microsoft Edge. This
27:19
still kind of makes me
27:21
annoyed. How am I going
27:24
to debug somebody else's? Like
27:26
somebody, a user says, I have
27:29
my autoplay doesn't work. You
27:32
can catch the error. So a
27:35
play method has switched to a promise.
27:38
So what you can do is you say await
27:41
video.play or audio.play.
27:44
And if you're not allowed to play, you catch
27:46
it. So just put a dot catch on the
27:48
end and then you can say,
27:50
oh, it's not done. The real trick
27:52
though is just listen for
27:55
any click at all on the
27:57
website and play something at that point. And then
27:59
you're in. I hate
28:01
that I hate all of this because like somebody
28:03
comes to me and they say hey I
28:06
click the toggle that says auto play your
28:08
videos don't autoplay the sites broken like I gotta
28:10
send an email or I gotta send a
28:12
response or You
28:14
know catch that or whatever at the moment
28:16
and say oh you haven't engaged enough with
28:19
the site for auto Polito work even though
28:21
you clicked the toggle that said please let
28:23
me autoplay like there has to be a
28:25
better permissions model than Yeah,
28:28
you know what give me give me just
28:30
a straight-up permission slide But
28:32
once you click the button that turns
28:34
on autoplay, there's your click. Yeah,
28:37
but what if I'm afraid Refresh the
28:39
page what if they refresh the topic? Doesn't
28:43
then then they have well,
28:45
no it's a good point. I Tested
28:49
it when I was doing my
28:51
autoplay and it was very easy to get
28:53
a High enough
28:55
media engagement score. I think
28:58
I think the user had to watch a
29:02
Couple minutes But
29:04
even with like a high enough engagement
29:06
store score upon loading a page
29:09
the browser still doesn't like it to immediately
29:12
start playing media when a
29:15
Page has been opened without some sort of click
29:17
or some sort of anything No,
29:20
you can do it if your media engagement score. No,
29:22
I know but it doesn't like it I'm
29:25
telling you doesn't like it the browser the
29:27
browser gets angry. It says no. Thank you.
29:29
Yeah No,
29:31
you're no you're wrong about that. Your
29:34
media engagement score is higher and I'm reading
29:36
it right now Of
29:38
media must be greater than seven
29:40
seconds So as long as
29:42
you can play something for seven seconds
29:44
that is an unmuted state You
29:48
can you could do that and I
29:50
bet you could get around that by playing a permission
29:52
flag. Just give nothing Yes, give me a yeah
29:55
Yes, true. Are you are you going
29:57
to allow this? Honestly, there's most websites
30:00
I don't want autoplay on unless
30:02
it is actually a video website
30:04
like Like
30:06
YouTube or a court my course platform and
30:09
guess what? I'm a big boy if that pops up
30:11
and says would you like the site to autoplay video?
30:13
I click no and feel good about that
30:17
Yeah, the browser making choices for me about
30:19
which sites I can autoplay videos. It's true
30:21
I think also people hate that though because
30:24
Another pop with permissions like you see this on
30:26
iOS all the time They pop a permission up
30:28
and they try to do like a fake permission
30:31
because if you're gonna click no They
30:33
don't want to show you the real one because then
30:36
you got to tell the user how to go into
30:38
your settings and and Turn it off. Like once they
30:40
hit no you're it's over. There's no normal people are
30:42
not turning that setting back on Yep,
30:45
man, no fun stuff,
30:47
huh permissions is a hard thing. Yeah. All right.
30:49
I think that's good enough for today Hopefully
30:52
you enjoyed that we will catch you later
30:55
Please peace You
Podchaser is the ultimate destination for podcast data, search, and discovery. Learn More