I would like to access the result of the following shell command,
youtube-dl -g "www.youtube.com/..."
to print its output direct url to a file, from within a python program. This is what I have tried:
import youtube-dl
fromurl="www.youtube.com/..."
geturl=youtube-dl.magiclyextracturlfromurl(fromurl)
Is that possible?
I tried to understand the mechanism in the source but got lost: youtube_dl/__init__.py, youtube_dl/youtube_DL.py, info_extractors ...
It's not difficult and actually documented:
import youtube_dl
ydl = youtube_dl.YoutubeDL({'outtmpl': '%(id)s.%(ext)s'})
with ydl:
result = ydl.extract_info(
'http://www.youtube.com/watch?v=BaW_jenozKc',
download=False # We just want to extract the info
)
if 'entries' in result:
# Can be a playlist or a list of videos
video = result['entries'][0]
else:
# Just a video
video = result
print(video)
video_url = video['url']
print(video_url)
For simple code,
may be i think
import os
os.system('youtube-dl [OPTIONS] URL [URL...]')
Above is just running command line inside python.
Other is mentioned in the documentation Using youtube-dl on python
Here is the way
from __future__ import unicode_literals
import youtube_dl
ydl_opts = {}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
ydl.download(['https://www.youtube.com/watch?v=BaW_jenozKc'])
Here is a way.
We set-up options' string, in a list, just as we set-up command line arguments. In this case opts=['-g', 'videoID']. Then, invoke youtube_dl.main(opts). In this way, we write our custom .py module, import youtube_dl and then invoke the main() function.
from __future__ import unicode_literals
import youtube_dl
ydl_opts = {}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
ydl.download(['Your youtube url'])
You can use 'format', 'continue', 'outtmpl' in ydl_opts
As example;
ydl_opts= {
'format': '22',
'continue': True,
'outtmpl': '%(uploader)s - %(title)s.%(ext)s',
'progress_hooks': [my_hook],
}
def my_hook(d):
if d['status'] == 'downloading':
print('Downloading video!')
if d['status'] == 'finished':
print('Downloaded!')
When you need to stop playlist downloading, Just add this code into ydl_opts.
'noplaylist': True;
Usage: python3 AudioFromYtVideo.py link outputName
import os
from sys import argv
try:
if argv[1] and argv[2]:
pass
except:
print("Input: python3 [programName] [url] [outputName]")
os.system('youtube-dl -x --audio-format mp3 -o '+argv[2]+' '+argv[1])
If youtube-dl is a terminal program, you can use the subprocess module to access the data you want.
Check out this link for more details: Calling an external command in Python
I would like this
from subprocess import call
command = "youtube-dl https://www.youtube.com/watch?v=NG3WygJmiVs -c"
call(command.split(), shell=False)
Related
I am trying to save the video title of a youtube video in a variable.
This is what I got so far:
import os
title = os.system('youtube-dl --get-filename -o "%(title)s.%(ext)s" '+url)
print(title)
Unfortunately, if I print the variable, it only returns 0.
Any ideas on how to solve this?
I found a solution that works well for me:
import os
import subprocess
url = "https://www.youtube.com/watch?v=7-qGKqveZaM"
title = subprocess.check_output('youtube-dl -e --get-title '+url, shell=True, universal_newlines=None)
#! /bin/python3
#Imports
import sys
import datetime
#Basic usage
print()
print()
print('Hello User. Welcome to ProjGURU, an innovative but basic project made by Unfree\'s CEO, Gururam. The current date and time is {}. Let\'s get right into the project.'.format(datetime.datetime.now()))
print()
lay1 = input('Please choose which programme to download and load.\n1.Tor\n2.Opera\n3.Chrome')
print()
#lay1 splitted
if lay1 == '1':wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
how do i execute the wget command
If your primary intention is to download that file, you can use the requests library, as Bruno pointed out in the comments. Install it via the command-line tool pip:
$ pip install requests
Then you can import the library and download your file as such:
import requests
# ... other code
if lay1 == '1':
with open('google-chrome-stable_current_amd64.deb', 'wb') as f:
r = requests.get('https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb')
f.write(r.content)
I have a python app, where I have a variable that contains multiple urls.
At this moment I use something like this:
for v in arr:
cmd = 'youtube-dl -u ' + email + ' -p ' + password + ' -o "' + v['path'] + '" ' + v['url']
os.system(cmd)
But this way I download just one video after another. How can I download, let's say 3 videos at the same time ? (Is not from youtube so no playlist or channels)
I not necessary need multi threading in python, but to call the youtube-dl multiple times, splitting the array. So from a python perspective can be on thread.
Use a Pool:
import multiprocessing.dummy
import subprocess
arr = [
{'vpath': 'example/%(title)s.%(ext)s', 'url': 'https://www.youtube.com/watch?v=BaW_jenozKc'},
{'vpath': 'example/%(title)s.%(ext)s', 'url': 'http://vimeo.com/56015672'},
{'vpath': '%(playlist_title)s/%(title)s-%(id)s.%(ext)s',
'url': 'https://www.youtube.com/playlist?list=PLLe-WjSmNEm-UnVV8e4qI9xQyI0906hNp'},
]
email = 'my-email#example.com'
password = '123456'
def download(v):
subprocess.check_call([
'echo', 'youtube-dl',
'-u', email, '-p', password,
'-o', v['vpath'], '--', v['url']])
p = multiprocessing.dummy.Pool(concurrent)
p.map(download, arr)
multiprocessing.dummy.Pool is a lightweight thread-based version of a Pool, which is more suitable here because the work tasks are just starting subprocesses.
Note that instead of os.system, subprocess.check_call, which prevents the command injection vulnerability in your previous code.
Also note that youtube-dl output templates are really powerful. In most cases, you don't actually need to define and manage file names yourself.
I achieved the same thing using threading library, which is considered a lighter way to spawn new processes.
Assumption:
Each task will download videos to a different directory.
import os
import threading
import youtube_dl
COOKIE_JAR = "path_to_my_cookie_jar"
def download_task(videos, output_dir):
if not os.path.isdir(output_dir):
os.makedirs(output_dir)
if not os.path.isfile(COOKIE_JAR):
raise FileNotFoundError("Cookie Jar not found\n")
ydl_opts = {
'cookiefile': COOKIE_JAR,
'outtmpl': f'{output_dir}/%(title)s.%(ext)s'
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
ydl.download(videos)
if __name__ == "__main__":
output_dir = "./root_dir"
threads = []
for playlist in many_playlists:
output_dir = f"{output_dir}/playlist.name"
thread = threading.Thread(target=download_task, args=(playlist, output_dir))
threads.append(thread)
# Actually start downloading
for thread in threads:
thread.start()
# Wait for all the downloads to complete
for thread in threads:
thread.join()
With this code
import os
with open('urls.txt') as f:
for line in f:
os.system("youtube-dl "+"--write-thumbnail "+"--skip-download "+"--yes-playlist " +line)
The first image in the playlist downloads, then I get an error message saying 'list' is not recognized as an internal or ex ternal command, operable program or batch file. In 'urls.txt' I have just one url of a Youtube playlist. The url is this:
https://www.youtube.com/watch?v=GA3St3Rf9Gs&list=PL-uc0GihCvU9s24BT_mvTzt3zm7e2uDGm
It's cutting off input after the & symbol. If I replace 'list' in the url with 'foo' I get the same message. What do I do to make youtube-dl accept playlist URL?
Your program has a major command injection security vulnerability. You have triggered this (with harmless code) by accident. You are executing
youtube-dl --write-thumbnail --skip-download --yes-playlist \
https://www.youtube.com/watch?v=GA3St3Rf9Gs&list=PL-uc0GihCvU9s24BT_mvTzt3zm7e2uDGm
Since the ampersand is a command character in shell scripts, you're running two commands
youtube-dl --write-thumbnail --skip-download --yes-playlist \
https://www.youtube.com/watch?v=GA3St3Rf9Gs
and
list=PL-uc0GihCvU9s24BT_mvTzt3zm7e2uDGm
Since there is no program with that name, the second command will likely fail.
To fix this, use proper subprocess invocations with subprocess:
import subprocess
with open('urls.txt') as f:
for line in f:
subprocess.check_call([
"youtube-dl",
"--write-thumbnail", "--skip-download", "--yes-playlist",
line])
All you have to do to fix this, quote the YouTube URL, as in:
yt-dlp --yes-playlist "https://www.youtube.com/watch?v=XArZ74galOE&list=PLDrswW4_QtejDZdLE4EOVXunQvqU18sPK"
Solved the problem.
Thanks to nav3916872
You can use the youtube_dl library directly in your script and pass the urls to download from.
import os
import youtube_dl
ydl_opts = {
'writethumbnail': True,
'skip_download': True,
'noplaylist': False
}
with open('urls.txt') as f:
sources = f.readlines()
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
ydl.download(sources)
in commandprompt , you just need to quote the url(with ampersand). You can try to escape the url(with ampersand) in the same way in python. Refer youtube-dl FAQ
I have a python script:
//test.py
import psutil
while True:
result = psutil.cpu_percent(interval=1)
print(result)
and then nodejs code:
//test.js
var PythonShell = require('python-shell')
pyshell = new PythonShell('test.py')
pyshell.on('message', function(message) {
console.log(message)
})
nothing happened when I executing node script. Please help me how to get data per second (like "real-time") from endless python code from Node and loggging it to console.
You need to flush STDOUT:
#test.py
import psutil
import sys
while True:
result = psutil.cpu_percent(interval=1)
print(result)
sys.stdout.flush()
It looks like it's a common issue with the python-shell npm package - https://github.com/extrabacon/python-shell/issues/81