Skip to content

Instantly share code, notes, and snippets.

@nneonneo
Last active April 2, 2024 04:57
Show Gist options
  • Star 34 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save nneonneo/f6b2d659ba76542e7d27e13598a6859c to your computer and use it in GitHub Desktop.
Save nneonneo/f6b2d659ba76542e7d27e13598a6859c to your computer and use it in GitHub Desktop.
YouTube-DL for Pythonista - download YouTube videos on your iPhone/iPad!
#!python3
'''
Directions:
- install yt-dlp via Pip (e.g. using (StaSh)[https://github.com/ywangd/stash] - `pip install yt-dlp`)
- add this script as a Share extension through Settings -> Share Extension Shortcuts
- while watching a video in the YouTube site or app, just share the video to Pythonista and select this script
- the video will download, and when it's done you can share the video file itself with any app (e.g. VLC)
Advanced usage:
- if you specify -audio as the script argument, this script will download audio only
- if you specify -stream as the script argument, this script will just grab the actual video URL and redirect you
to VLC, which will stream the video (without interruptions or ads!)
'''
from __future__ import unicode_literals
import yt_dlp as youtube_dl
import appex
import console
import clipboard
import os
import sys
try:
# We cannot use ffmpeg on iOS
from yt_dlp.postprocessor import FFmpegPostProcessor
FFmpegPostProcessor.available = False
except ImportError as e:
pass
outdir = os.path.expanduser("~/Documents/Downloads")
try:
os.mkdir(outdir)
except FileExistsError:
pass
if appex.get_attachments():
# e.g. share from YouTube app
url = appex.get_attachments()[0]
elif appex.get_urls():
# e.g. share from Safari
url = appex.get_urls()[0]
elif appex.get_text():
url = appex.get_text()
elif clipboard.get():
url = clipboard.get()
print("URL: ", url)
if not url or not url.startswith("http"):
url = input("No URL found - enter URL to download: ")
ydl_opts = {'outtmpl': os.path.join(outdir, '%(title)s.%(ext)s')}
if '--audio' in sys.argv[1:] or '-audio' in sys.argv[1:]:
ydl_opts['format'] = 'bestaudio'
if '--stream' in sys.argv[1:] or '-stream' in sys.argv[1:]:
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(url, download=False)
from objc_util import UIApplication, nsurl
from urllib.parse import urlencode
app = UIApplication.sharedApplication()
params = urlencode({'url': info['formats'][-1]['url']})
#app.openURL_(nsurl('vlc-x-callback://x-callback-url/stream?' + params))
#app.openURL_(nsurl('infuse://x-callback-url/play?' + params))
app.openURL_(nsurl(info['formats'][-1]['url']))
else:
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(url, download=True)
filepath = ydl.prepare_filename(info)
console.open_in(filepath)
@entisocial
Copy link

entisocial commented Dec 21, 2020

Just wondering, would there be a way to stream the video without VLC to get them to play in Picture in Picture? As I understand it, the script makes the video AVplayer friendly so is there a possibility?

@nneonneo
Copy link
Author

nneonneo commented Dec 22, 2020

You just need to change the openURL line to open the stream in your player of choice. Some ideas:

Option 1: you could open the URL in Safari, which supports many but not all formats, which will be the simplest approach. Use the line

app.openURL_(nsurl(info['formats'][-1]['url']))

Option 2: you could use, for example, the third-party Infuse app, which supports PIP and probably every YouTube video format (not fully tested). Use the line

app.openURL_(nsurl('infuse://x-callback-url/play?' + params))

@entisocial
Copy link

Thanks a lot, the safari solution works perfectly for my usage!

@j3d1c4nna
Copy link

Hi. I’m loving using this code via Pythonista. This may be a silly question, but what’s the process to specify —stream as the argument?
Thanks

@nneonneo
Copy link
Author

nneonneo commented Feb 2, 2021

Nope, not a silly question! When setting up the share extension, just add --stream as the argument. Note: if you try to enter two dashes in a row, iOS will autocorrect it to a single em dash (—) which won't work - to bypass this, I recommend copying the argument from here, or just typing in two dashes separated by some character (e.g. -x-) then deleting the character in the middle.

@j3d1c4nna
Copy link

Ahh, perfect! I’d set up the share extension once, when I first installed pythonista, and hadn’t even noticed the option to set an argument there!
thanks

@bububy
Copy link

bububy commented Nov 19, 2021

How do I set it up to download in mp3

@nneonneo
Copy link
Author

nneonneo commented Dec 7, 2021

@bububy I've just updated the gist to support downloading only audio. Add -audio as the argument when setting up the share extension. (I've also updated the gist to support single-dashed arguments, i.e. -audio and -stream, to make it easier to enter these arguments.)

@bububy
Copy link

bububy commented Dec 7, 2021

@nneonneo ok so I’m a little bit of a noob when it comes to this Stuff where would I put the -audio

@nneonneo
Copy link
Author

nneonneo commented Dec 7, 2021

Settings (gear icon at the bottom of the sidebar menu) -> Share Extension Shortcuts -> [+] icon to add a new shortcut. Then select the youtube-dl.py script and add the -audio argument in the Arguments box.

@bububy
Copy link

bububy commented Dec 9, 2021

@nneonneo thank you

@elepopp
Copy link

elepopp commented Jan 17, 2022

大佬 下载怎么只有几十k 太慢了 有什么办法吗

@nneonneo
Copy link
Author

I've heard that youtube_dl can be slow if YouTube detects that you're using a bot, and that yt_dlp bypasses this limitation.

You can try the following:

pip install yt-dlp

and then change

import youtube_dl

to

import yt_dlp as youtube_dl

I think no other changes are needed to use yt_dlp as it should mostly be a drop-in replacement. If it works for you, I can update the Gist.

@elepopp
Copy link

elepopp commented Jan 17, 2022

谢谢 换成yt-dlp速度正常了

@nneonneo
Copy link
Author

Thanks, I updated the Gist.

@camelottt
Copy link

How to fix the “this may be inappropriate for viewers” or something along those lines problem?

@sixplus0
Copy link

sixplus0 commented May 9, 2022

Thanks so much!! And...want to know how to change for getting the best video and the output format with mp4?

@nneonneo
Copy link
Author

@camelottt There isn’t a great solution to this that I know of. If you can extract your YouTube cookies you can provide them to yt-dlp, but you’ll likely need a computer to do that.

@sixplus0 Yes, I believe you can set ydl_opts['format'] = 'mp4' to get the best MP4 format video.

@sixplus0
Copy link

@sixplus0 Yes, I believe you can set ydl_opts['format'] = 'mp4' to get the best MP4 format video.

Thank you! Tried that, 720P is achievable. As I intended to get higher resolution using ydl_opts['format'] = 'bestvideo' , the best video with format webm is available without audio, but It seems that FFmpeg could not be launched in Pythonista...I am getting stuck.

@nneonneo
Copy link
Author

Yes, unfortunately we cannot use ffmpeg as we can’t add native binaries on iOS. There may be third party apps that can merge and/or convert the video and audio file if downloaded separately.

@sixplus0
Copy link

Well understood! Appreciate your GREAT help and the script enlightens me A LOT!!! THANKS echos~~~

@gaetschwartz
Copy link

gaetschwartz commented Jul 14, 2022

Hi, I was wondering if we could access the ~/Documents/Downloads folder somehow, is it just a temporary folder or a permanent one ? If permanent, then sharing the file to VLC would mean we have twice the file isn't it ?

@nneonneo
Copy link
Author

Yes, it should be accessible directly in Pythonista, via the script library file browser under This iPhone. The file will be copied from here to VLC, but you may delete the copy in Pythonista afterwards.

@ysiegel29
Copy link

How can you change the format to MP3 when using the -audio extension? Thank you! Great script!

@ysiegel29
Copy link

Fyi I could not find a way to convert to mp3 (no support for ffmpeg on iOS) but if you replace bestaudio by m4a you get an mpeg4 audio file that worked for my use case.

@nneonneo
Copy link
Author

Yeah, unfortunately we can't support ffmpeg, and as far as I understand it, YouTube does not encode their audio in MP3 format. Glad to hear that m4a worked for your case.

@rafcontreras
Copy link

I've found the best format to send to VLC or Infuse is:

ydl_opts['format'] = 'bv+ba'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment