Hi! My name is Eduardo Ochs,
I'm the author of an Emacs package called eev,
and this video is about a function that I added
to eev in March... it's called
`find-yttranscript-links'...
and... well, this page is about this video
and that function, with all the details...
and that function is inspired by a blog post
that Andrea Giugliano wrote in...
actually, two blog posts -
in the end of March...
the first blog post was called
"An Elisp snippet to download
YouTube video transcripts"...
and the second one was about rewriting
his function of the first blog post
in a slightly different style.
When I read those blog posts
I immediately thought that WOW,
I _need_ something like that in eev,
but I would like to rewrite it
in the style that I prefer to put the
things in eev in...
and that's the reason for the dog
with the square haircut here -
I'm going to call him the "square dog"...
when people say "dog" no one expects
a square dog, so this is not the dog
that people would expect by default...
and the interface that this function uses
is as unexpected as a square dog.
So let me show how this thing works.
I prepared two examples here.
The first example uses a video that I
have not downloaded with youtube-dl yet,
and the second example uses a video that
I have downloaded.
A few months ago I wanted to convince
a friend to read this manga here,
"Lone Wolf and Cub"...
and I found this video about Lone Wolf
and Cub, aind I wanted to to send him a
link to a specific part of the video...
so I watched first the whole video, and
then I wanted to find a specific part,
and I only remembered a few keywords of
it... so, what did I do?
First of all... uh, no, one second.
This thing here, this sequence of 11
characters, is what I call the "hash"
of the video, and YouTube videos
are identified by their hashes.
When I run `M-x find-youtubedl-links' -
this is my standard function for
downloading videos from YouTube and for
doing things related to downloaded
videos...
and when I run that function it detects
the hash around point and it
does some things with that hash...
in this case the hash is going to be
this one, "aZWq6CEzhuQ"...
and `find-youtubedl-links' is going to
generate a temporary buffer
in which several parts of it
were replaced by that hash.
so this thing here is the hash,
and these other... stubs
have not been replaced yet...
and one thing that I'm going to do is
that I'm going to replace the stem
by "lonewolf".
Let me duplicate this line and in this
copy I'm going to replace the "{stem}"
by "lonewolf".
if I execute this sexp here it will
regenerate this buffer with these values
for some variables of the template, and
the "{stem}" that appears here, here,
here, and in lots of other places is
going to be replaced by "lonewolf".
Let me do that now...
Here - the buffer was slightly changed...
here we see "lonewolf" in several
places... and let me delete the parts that
I'm not going to use. I'm not interested
in this part here... by the way,
this sexp here goes to a tutorial
that explains how to use youtube-dl...
sorry, how to use youtube-dl from eev.
If we follow this we go to this
tutorial here, to this section, that
starts by explaining what is the hash of
the video, and so on... but let me go back.
I also do not want this section here, I
said that I do not want to download this
video so I also do not want these things
here... remember that this is a
temporary buffer, so I can do any mess
that I want with it...
this section is about playing the local
copy - I do not have a local copy...
I'm interested in these parts here.
If I execute this then Emacs
is going to call Google Chrome
with a certain URL to play the video
starting from a certain position. For
example, if I replace this by 2:34, if
executed this it will play the video
with this hash starting from this
position...
and if I execute this sexp here
it will define a function with this "code"
in its name, so it's "lonewolf"...
the code is here... and this function
here, `file-lonewolfvideo', it will play
that video from a certain point...
and it was defined as a function
that plays that video by opening a
browser on a certain URL that plays
the video from a certain position.
So, for example, if I put 2:34 here
it will play the video starting from
2:34... but I do not want to play the
video now.
I want to run this. If I run this sexp
here it will open another temporary buffer
with another name, so it will not delete
this temporary buffer... note that this
temporary buffer is called
"*find-youtubedl-links*"...
let me execute this... it opens another
temporary buffer, called
"*find-yttranscript-links*"
let me run this with a smaller font...
remember that when I use eepitch the
main key is f8, and f8 acts in one way
on lines that start with a red star,
like these four lines here, and in
another way on lines that do not start
with red stars...
and I usually use lines with red stars
to set up a target buffer, but I can also
use them to do other kinds of setups.
These three lines here will
prepare a target buffer that is running
python, but in this case I will usually
execute these four lines here,
starting from this one...
and the action of this first one -
remember that when we execute
lines that start with red stars with f8
the rest of the line after the red star
is executed as Lisp...
So... if I start by typing an f8 here
the action of this first line is to put
this buffer here, that is in fundamental
mode, in Python mode...
so now the colors are more expressive.
And now I'm going to run this these
three lines again, they will kill this
target buffer and will regenerate it
again...
and now I'm going to use f8 again to
send these lines to the target buffer.
Remember that when I type an f8 on a
line that do not start with a red star
the f8 sends the line to the target
buffer...
usually the target buffer is running
an interactive program, and the program
thinks that the user had typed the
contents of that line.
So I'm going to send these commands here
to this Python interpreter here,
starting by this one.
This one here, that calls this
function with a very long name here,
takes a few seconds to run, so I'm going
to type f8 here and wait until it's
done... it was quick.
And now I'm going to run these things
here, and this print here.
And this print here prints the
transcript of the video in a certain
format. Sometimes I want other formats so
it's easy to switch to another format...
in this case when I ran these three lines here
I defined two variables, trits0 and trits1,
for a transcript... and the second definition
for trits1 over... oh god, how do I say
that in English? Has overridden
the previous one... so I executed this,
and then this, and the current definition
of trits1 is the one that corresponds to
this expression here,
that gives me this format...
if I execute this line here I'm going
to get another format... another
definition for trits1 and another
format. Let me do that now, and let me
print the current value of trits1...
it is in this much shorter format.
I do not want to explain how to use this
this shorter format now... the other
format is easier to understand.
So let me use the previous format again...
and now I have a sequence of sexps, and
each one of these sexps is a link that...
I mean, when I execute it it is going to
act as a hyperlink that does something,
and this something is to
invoke Google Chrome to play
this video here
starting from a certain position.
And when I wanted to send a part
of this video to my friend
I wanted to show him the part that
mentioned Akira Kurosawa...
so let me search for Kurosawa here...
found it! Let me see...
I want to start a few seconds before
that, let me see where... ah, here:
"...but Lone Wolf and cub is above all
cinematic, blah blah blah blah... it
uses the vocabulary of movies..."
I want to start from this position, so
let me check if this is what
I'm looking for... let me execute this.
It will open another tab in the browser...
it takes a few seconds...
no, sorry, many seconds...
and it plays an ad...
that's the part that I'm interested in.
I'm not interested in the ads.
Let me close the YouTube window.
Anyway, so this is the part that I want,
and I can copy that to my buffer with
the annotations about this video...
and let me delete this and go back to
this thing here, where I saved some
hyperlinks... so I was saving these
hyperlinks here, and of course
I'm not going to use all of them,
but the ones that can be useful, that
deserve to be saved if I want to replay
this action at some point, are
these ones. So, these ones create
a kind of setup in which this function
is defined, and now that this function
is defined I can use this sexp here to
play the video from a certain position.
But let me go back. I said a long time
ago that I was going to show two
examples. In the first one I was going to
use a video that I do not have a local
copy of, that is the first one... and the
second one is an example in which I use
a video that I have downloaded the local
copy: this one.
Remember that I can either type
`find-youtubedl-links' here...
but I can also type
`find-yttranscript-links' here...
it also detects the hash around point.
Let me see... no, I want the other
one, here... and I want to define
short names for the hyperlinks to this
video. I'm going to use this stem here,
"haskelltocore".
Let me use a smaller font...
this title here was derived from...
I mean, Emacs looked at my directory
with local copies of videos that I
have downloaded using
`find-youtubedl-links', and it found
that I have a video with this hash here,
with this title here, and with this
extension. So this is the title,
this is the hash, this is the
extension, and so on. And I have just
adjusted this by hand, and I'm going
to run this sexp here to regenerate
this buffer, so these "{stem}"s
here are going to be replaced by
"haskelltocore".
Again, I'm going to delete the things
that I do not want to use...
I have already downloaded the video, so I
do not need this, and I'm going to
delete this part that plas the video
on YouTube because I just want the
local copy.
And now let me copy this to my notes.
I want to execute this sexp here,
and this sexp here is going to define
the function `find-haskelltocorevideo',
this function here...
and it's going to define
that function in a way that is very
different from the way that I defined
this function here. When I ran
`code-youtubevideo' with these arguments
here it defined `find-lonewolfvideo'
as a function that plays a video on
YouTube by telling a browser to open
a certain URL,
and now what I'm going to do is that I'm
going to define the function... I mean,
this very long sexp here defines this
function here as a function that plays
a local copy of a video - a local video.
The function that plays local copies does
not know if the local copy
was downloaded from YouTube
or if it is something else.
So, this sexp here plays the local
copy of the video -
it's a very good talk about Haskell -
and suppose that I want to find
something that I remember
that I saw in the video
when I watched it, and I remember a few
keywords about it.
So, I can use this to access the
transcript...
note that
this sexp here was invoked with
the hash of the video,
and with this short name here, that can
be used to generate the name of this
function here...
If I run this I get this
temporary buffer, and I want to execute
this block here - let me do that now...
this line here takes several seconds
to run, so I'm going to press f8 once and
then wait for the next prompt here...
got it. And now I'm going to generate
these variables here, and I'm going to
print the contents of the variable
trits1... it is this thing here...
let me choose a keyword...
let me search for "monad", for example -
just a random keyword... I don't remember
what is the part that I was
looking for, sorry...
let's see what happens when I run
this thing here...
it plays a local copy.
So, yeah, that's it. So: I can use that
to find things in videos...
if I want to download the
transcript of a video I need something
that is a bit tricky...
if I just run this sexp here,
this sexp with `find-youtubedl-links',
this block here, that has the commands
for downloading the video...
in this block youtube-dl is called with
several different command line options...
I sometimes choose one that downloads the
video with low resolution, and
sometimes I run this one to download the
the best possible version...
and note that I here I have an option
that says that I want youtube-dl to
download the subtitles of the video, and
for YouTube subtitles and transcripts
are different things... subtitles are
edited by hand, and transcripts are
generated automatically from the
program that does speech recognition...
and to download the transcript I need
other options... they are not here...
I need another trick, so I need to
change them by hand...
so when I downloaded the copy of this
video I did not download the
transcript. The local copy does not have
subtitles...
I'm not going to show how to download
this transcript now, and to
convert it to a format that makes it
work as subtitles for the video,
but it is possible to do that.
It's not the focus of the video
and I did not prepare that now...
anyway, let me go back. This is what I
wanted to show... no, there's one
thing missing, but the main idea
is that I have enhanced my
`find-youtubedl-links'
with a way to download the transcript
of a video.
This way can be accessed by this last
block here in the temporary buffer...
and so this is new - this is something
that I added to `find-youtubedl-links'
in March... and also,
there are several
new tricks here. One trick, that is not
very obvious and not everyone has
figured out that red star lines can do
that, is that we can use a red star line
to do other things of setups, like
changing the mode of a buffer - even
a temporary buffer...
so this one puts it in Python mode.
The rest is more familiar...
and note that this first line here says
to Python to import a library that
downloads transcripts from YouTube...
either transcripts or subtitles, it
works for both cases...
when people are running this for the
first time they probably do not have
that library... so what can they do?
This sexp here calls pip3, that is the
package manager for Python 3, with this
argument here, that is the name of our
package...
and this thing here opens a temporary
buffer that lets me
install that package.
In this case I already have that package
installed, so I do not need to run
these things...
and let me show something that I have
let's say, this module of eev, just a
few days ago. I've added these two
functions here. This one here
can be used to
show information about a package
that is already installed... let me
copy these two lines to my notes,
one second...
my notes are here...
so this sexp here
is also like a square dog, it's an
unusual kind of interface...
and it has this small Python program
here, that mentions the name of a package
in a certain point...
and in this small program here I import
a library called "importlib", that
handles "import" and the files that
import uses, and
its sublibrary metadata,
and pretty-print, and so on...
let me do that now...
here is a new Python
interpreter and I'm going to to run
these things...
if I do not have this package then this
import will fail, but I have this
package.
And now I'm going to run these things
here to get information about this local
package. Its init file is here...
now I'm going to run importlib with
a certain submethod to get information
about this package...
and I'm going to print some information
that is in this that data structure
here... and ta-da!
This is quite primitive, but basically
it shows how to obtain
information about Python a package
that is already installed
in a very low-level way...
so I think that people who are learning
Python are going to find this interesting.
And there's something similar, but that
checks the remote repository of Python
packages...
if execute this I get another
temporary buffer here...
and here I have
some information about the
functions that I'm going to to use now...
basically I'm going to
to ask this site here about information
about this package...
and well, it's...
sorry I'm not going to give
the details now... let me just show what
this does.
Let me run this again...
this takes a second because it has to
to talk to the internet,
and now I'm going to
explore this data structure a bit.
For example, this subfield of a subfield
here
has information about the home page of
the upstream version of this package...
I can visit this URL here...
I have just asked Emacs to open
a new tab in the browser with
this URL here... so
this is all the information about this
package, and
I think that not all these files are
downloaded when I install this package...
some of these files may be
documentation, examples...
I do not know this very well yet...
Yeah, so: that's it.
Let me finish the video now. So:
yeah, bye! =)