17
$\begingroup$

I just downloaded Mathematica 13 for Mac. There is a new function called Video[] which should stream videos from a URL all inside of a Mathematica notebook.

I have been looking forward to this functionality for a while. I would like my students to be able to watch my youtube lecture videos inside of a Mathematica in a window surrounded by my text and animations. I know you can get this functionality in the Wolfram Cloud but I lose too many other features that the desktop version of Mathematica offers. I do not care for this option. I'm only looking for a desktop solution.

I tried entering the following code in Mathematica desktop as described in the documentation center but it doesn't seem to work.

Video[URL["https://www.youtube.com/embed/HQefO4iLM0g"]]

I get the error:

VideoStream::conopen: A connection could not be established to the resource at URL[https://www.youtube.com/embed/HQefO4iLM0g]. Check that your internet is connected or that any authentication credentials provided are correct.

My internet is connected and the URL is valid. Also, it's a public link so I'm not sure what credentials I would need to add if any. Do you have any ideas?

$\endgroup$
1
  • $\begingroup$ This is unlikely to work without some kind of partnership between Wolfram and YouTube. Downloading YouTube videos is intentionally made difficult by YouTube. An option may be to ask your students to install youtube-dl, and then write a small wrapper function that downloads the video using youtube-dl, and wraps the resulting file in Video. Another option would simply be hosting a video file yourself somewhere outside of YouTube (possibly including, for instance, CloudPublish). $\endgroup$
    – Carl Lange
    Commented Dec 16, 2021 at 18:50

2 Answers 2

16
$\begingroup$

We know Mathematica supports communication with different programming languages via external connectors. I will show a way with Python here. Main idea is to import the YouTube streaming link using an external python library (pytube).

I assume OP has Python installed in the system and it can be accessed via functions like ExternalEvaluatein Mathematica. Now to keep things really clean we will follow these standard practices.

Initial setup

Create a python virtual environment named youtube for this specific python task. We will use few handy functions from the function repository.

env = ResourceFunction["CreatePythonVirtualEnvironment"]["youtube"];
register = FindExternalEvaluators["Python"][env];
(* location of the virtual environment executable *)
target = If[register["Registered"], register["Target"], None]

C:\Users\rob\Documents\youtube\Scripts\python.exe

If we have Python ready with the virtual environment youtube registered successfully (meansthe above variable target should point to a file location and not be None) then we initiate a session and install the external library pytube.

(* start external python session within the virtual environment *)
session = StartExternalSession[<|"System"->"Python","Target":>target|>];
(* install the 'pytube' library *)
ResourceFunction["PythonPackageInstall"][session, "pytube"];
DeleteObject[session]

This initial setup takes a bit of time but only needed to be done once.

Programmable access to YouTube video

Lets copy paste few lines of pytube specific code via fast Googling. More info here in docs.

(* virtual env's python executable location *)
target = "C:\\Users\\rob\\Documents\\youtube\\Scripts\\python.exe";
(* pytube specific code *)
code = StringTemplate["
from pytube import YouTube
yt = YouTube('``')
yt.streams.filter(file_extension='mp4').get_by_itag(22).url
"];
(* start a session where we have pytube installed already *)
session = StartExternalSession[<|"System"->"Python","Target":>target|>];
getStreamingURL = ExternalEvaluate[session, code[#]] &;

We can have a VideoStream object for any public YouTube video URL now! Just pass the target YouTube video's url to the function getStreamingURL.

stream = VideoStream[getStreamingURL["https://www.youtube.com/embed/HQefO4iLM0g"]]

We have access to this stream programmatically from Mathematica.

VideoPlay[stream];
Dynamic[stream["CurrentFrame"]]

enter image description here

Let's pause the video to take screenshot.

VideoPause[stream]

At this point it should be possible to make a simple video player. There is an example in VideoStream documentation:

https://wolfram.com/xid/0rtdyu3b6-sx6zp0

Clean up time!

Once we are done we can delete the python session started externally via StartExternalSession.

 DeleteObject[session]

If needed we can also safely get rid of the virtual environment (named youtube) created for this experiment by deleting the root directory named youtube in the path (was stored as target above) of the python executable for this environment.

If[StringQ[target],
 DeleteDirectory[
  Composition[
    FileNameJoin,
    Take[#, UpTo[First@Flatten@Position[#, "youtube"]]] &,
    FileNameSplit
   ]@target,
  DeleteContents -> True
 ]
]
$\endgroup$
2
  • 2
    $\begingroup$ Thank you! I’m not familiar with Python but this gives me the motivation to learn. Does your solution allow the end user, who opens my notebook on their own machine, to play the videos in the notebook using the free Wolfram Player? Or would they also need to install python? $\endgroup$
    – B flat
    Commented Dec 17, 2021 at 3:33
  • $\begingroup$ @Bflat You are welcome. As you can see we are using Python only to get the right streaming link for a given YouTube video. Once you have the link (getStreamingURL returns the link) you can just use it in your Mathematica code and the distribute to end users who won't need to have python installed in their system. $\endgroup$ Commented Dec 17, 2021 at 8:36
10
$\begingroup$

I think the issue might be with the nature of the content in this URL. It's not that you are not been able to access the URL, as you can check yourself with running either

URLRead["https://www.youtube.com/embed/HQefO4iLM0g"]

which should return 200 OK, or

Import["https://www.youtube.com/embed/HQefO4iLM0g","Text"]

which will return the corresponding HTML. As you can see in the later response, it's mostly Javascript that is been executed by the browser to show you the video. I think Video[URL[...]] expects a valid video stream, and cannot execute an arbitrary Javascript, which is required to display this video. (If you observe Network tab in Google Chrome developer tools, you'll notice that Youtube constantly fetches small portions of the video from an ever increasing list of URLs.)

Youtube certainly doesn't make it easy for you to just grab the video stream, bypassing their chrome and ads.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.