When using my code bellow (It turns YouTube videos into ASCII with audio) The latency between the audio and video grows bigger each frame (I have tried many different wait times) I was wondering if there is a way to change the code to make it so the wait key changes depending on how much latency there is. I have only been coding for 6 months so sorry if there is any bad code.
import pytube
import os
import cv2
import PIL.Image
import winsound
from moviepy.editor import *
from pydub import AudioSegment
import threading
import time
##################################################
# downloads the youtube video and lets you input the path for where it should be saved
url = input ("Enter the you youtube url: \n\n")
path = input ("Enter the path where you want the youtube video to be saved: \n\n")
try:
youtube = pytube.YouTube(url)
streams = youtube.streams.all()
video = youtube.streams.get_highest_resolution()
video.download(path)
print ("Done!")
except:
print ("\nYoutube video has coppy righted material so it can not be downloaded. Try again with a different video")
##################################################
#locates all the files with the file extension .mp4
for root, dirs, files in os.walk(path):
for file in files:
if file.endswith(".mp4"):
file_name = (file)
file_path = (os.path.join(root,file))
print (file_name)
print (file_path)
##################################################
mp3_file = (path+"\\")
mp3_file = (mp3_file+"audio.mp3")
mp4_file = (path+"\\")
mp4_file = (mp4_file+file_name)
VideoClip = VideoFileClip(mp4_file)
audioclip = VideoClip.audio
audioclip.write_audiofile(mp3_file)
audioclip.close()
VideoClip.close()
sound = AudioSegment.from_mp3(mp3_file)
sound.export(path+"/audio.wav", format = "wav")
##################################################
def a():
# Ascii characters used to create the output
ASCII_CHARS = ["#", "#", "S", "%", "?", "*", "+", ";", ":", ",", "."]
def resized_gray_image(image ,new_width=80):
width,height = image.size
aspect_ratio = height/width
new_height = int(aspect_ratio * new_width)
resized_gray_image = image.resize((new_width,new_height)).convert('L')
return resized_gray_image
def pix2chars(image):
pixels = image.getdata()
characters = "".join([ASCII_CHARS[pixel//25] for pixel in pixels])
return characters
def generate_frame(image,new_width=80):
new_image_data = pix2chars(resized_gray_image(image))
total_pixels = len(new_image_data)
ascii_image = "\n".join([new_image_data[index:(index+new_width)] for index in range(0, total_pixels, new_width)])
sys.stdout.write(ascii_image)
os.system('cls' if os.name == 'nt' else 'clear')
cap = cv2.VideoCapture(mp4_file)
print (cap)
try:
while True:
ret,frame = cap.read()
cv2.imshow("frame",frame)
generate_frame(PIL.Image.fromarray(frame))
cv2.waitKey(1)
except:
threading.Thread(target=c).start()
##################################################
def b():
winsound.PlaySound(path+"/audio.wav",winsound.SND_FILENAME)
##################################################
def c ():
os.remove (mp3_file)
os.remove (mp4_file)
os.remove (path+"/audio.wav")
threading.Thread(target=a).start()
threading.Thread(target=b).start()
I am using the IDLE editor and Python 3.7, and I would like to know why my code is not playing multiple audio files (sequentially) and sometimes not playing audio at all:
import re
import wave
import pyaudio
import _thread
import time
class TextToSpeech:
CHUNK = 1024
def __init__(self, words_pron_dict:str = 'cmudict-0.7b.txt'):
self._l = {}
self._load_words(words_pron_dict)
def _load_words(self, words_pron_dict:str):
with open(words_pron_dict, 'r') as file:
for line in file:
if not line.startswith(';;;'):
key, val = line.split(' ',2)
self._l[key] = re.findall(r"[A-Z]+",val)
def get_pronunciation(self, str_input):
list_pron = []
for word in re.findall(r"[\w']+",str_input.upper()):
if word in self._l:
list_pron += self._l[word]
print(list_pron)
delay=0
for pron in list_pron:
_thread.start_new_thread( TextToSpeech._play_audio, (pron,delay,))
delay += 0.145
def _play_audio(sound, delay):
try:
time.sleep(delay)
wf = wave.open("sounds/"+sound+".wav", 'rb')
p = pyaudio.PyAudio()
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True)
data = wf.readframes(TextToSpeech.CHUNK)
while data:
stream.write(data)
data = wf.readframes(TextToSpeech.CHUNK)
stream.stop_stream()
stream.close()
p.terminate()
return
except:
pass
if __name__ == '__main__':
tts = TextToSpeech()
while True:
tts.get_pronunciation(input('Enter a word or phrase: '))
I have a list of audio files that will play in a certain order, depending on what word I type in, when running the code. The code has no errors, but when I run it, when I type in a word, it only plays the first audio file needed (Example: When I type in "buy" it requires these two sounds: "b" and "ie" played together), but it only plays the first sound, "b", and sometimes no sound at all.
Why isn't it playing multiple audio files? I know that lots of people have been having this issue, but haven't been able to solve it.
Thank you for your help in advance, it is greatly appreciated :)
I've created a python Flask video file streamer resource that works well when getting the file in a web browser but is not working when using ffmpeg.
The flask resource is:
from flask_restful import Resource, Api
class Mp4(Resource):
def get(self,grtv,data,canal,arquivo):
path = os.path.abspath('../mp4/' + str(canal) + '/' + str(data) + '/' + str(arquivo))
print(path)
def generate():
with open(path, "rb") as f:
chunk = f.read(1024)
while chunk:
yield chunk
chunk = f.read(1024)
try:
t = os.stat(path)
size = str(t.st_size)
return Response(generate(),mimetype='video/mp4',headers={"Content-Type":"video/mp4","Content-Disposition":"inline","Content-Transfer-Enconding":"binary","Content-Length":size})
except Exception as e:
result = {'result': e}
return result
The ffmpeg command is:
ffmpeg -loglevel debug -i <url> out_teste4.mp4
where url is de address of the streaming video.
The ffmpeg most important output is:
ffmpeg output screenshot 1
ffmpeg output screenshot 2
I've already tried increasing 'analyzeduration' and 'probesize' options.
ffmpeg version: 3.4.2-1~16.04.york0.2.
python version: 3.5.2.
Does anyone can help me to get the video files with ffmpeg? Suggestions can be both on changing the API or the ffmpeg command.
Thank you all!
I have been using pytube to download youtube videos in python. So far I have been able to download in mp4 format.
yt = pytube.YouTube("https://www.youtube.com/watch?v=WH7xsW5Os10")
vids= yt.streams.all()
for i in range(len(vids)):
print(i,'. ',vids[i])
vnum = int(input("Enter vid num: "))
vids[vnum].download(r"C:\YTDownloads")
print('done')
I managed to download the 'audio' version, but it was in .mp4 format. I did try to rename the extension to .mp3, and the audio played, but the application (Windows Media Player) stopped responding and it began to lag.
How can I download the video as an audio file, in .mp3 format directly? Please provide some code as I am new to working with this module.
How can I download the video as an audio file, in .mp3 format directly?
I'm afraid you can't. The only files available for direct download are the ones which are listed under yt.streams.all().
However, it is straightforward to convert the downloaded audio file from .mp4 to .mp3 format. For example, if you have ffmpeg installed, running this command from the terminal will do the trick (assuming you're in the download directory):
$ ffmpeg -i downloaded_filename.mp4 new_filename.mp3
Alternatively, you can use Python's subprocess module to execute the ffmpeg command programmatically:
import os
import subprocess
import pytube
yt = pytube.YouTube("https://www.youtube.com/watch?v=WH7xsW5Os10")
vids= yt.streams.all()
for i in range(len(vids)):
print(i,'. ',vids[i])
vnum = int(input("Enter vid num: "))
parent_dir = r"C:\YTDownloads"
vids[vnum].download(parent_dir)
new_filename = input("Enter filename (including extension): ")) # e.g. new_filename.mp3
default_filename = vids[vnum].default_filename # get default name using pytube API
subprocess.run([
'ffmpeg',
'-i', os.path.join(parent_dir, default_filename),
os.path.join(parent_dir, new_filename)
])
print('done')
EDIT: Removed mention of subprocess.call. Use subprocess.run (unless you're using Python 3.4 or below)
I am assuming you are using Python 3 and pytube 9.x, you can use the filter method to "filter", the file extension you are interested in.
For example, if you would like to download mp4 video file format it would look like the following:
pytube.YouTube("url here").streams.filter(file_extension="mp4").first()
if you would like to pull audio it would look like the following:
pytube.YouTube("url here").streams.filter(only_audio=True).all()
Hope that helps anyone landing on this page; rather than converting unnecessarily.
You will need to install pytubemp3 (using pip install pytubemp3) latest version 0.3 + then
from pytubemp3 import YouTube
YouTube(video_url).streams.filter(only_audio=True).first().download()
Pytube does not support "mp3" format but you can download audio in webm format. The following code demonstrates it.
from pytube import YouTube
yt = YouTube("https://www.youtube.com/watch?v=kn8ZuOCn6r0")
stream = yt.streams.get_by_itag(251)
the itag is unique id to get file with sppecific resolution
stream.download()
For mp3 you have to convert (mp4 or webm) file format to mp3.
With this code you will download all the videos from a playlist and saving them with the title from youtube in mp4 and mp4 audio formats.
i used the code from #scrpy in this question and the hint from #Jean-Pierre Schnyder
from this answer
import os
import subprocess
import re
from pytube import YouTube
from pytube import Playlist
path =r'DESTINATION_FOLER'
playlist_url = 'PLAYLIST_URL'
play = Playlist(playlist_url)
play._video_regex = re.compile(r"\"url\":\"(/watch\?v=[\w-]*)")
print(len(play.video_urls))
for url in play.video_urls:
yt = YouTube(url)
audio = yt.streams.get_audio_only()
audio.download(path)
nome = yt.title
new_filename=nome+'.mp3'
default_filename =nome+'.mp4'
ffmpeg = ('ffmpeg -i ' % path default_filename + new_filename)
subprocess.run(ffmpeg, shell=True)
print('Download Complete')
Download the video as audio, then just change the audio extension to MP3:
from pytube import YouTube
import os
url = str(input("url:- "))
yt = YouTube(url)
video = yt.streams.filter(only_audio=True).first()
downloaded_file = video.download()
base, ext = os.path.splitext(downloaded_file)
new_file = base + '.mp3'
os.rename(downloaded_file, new_file)
print("Done")
here is a mildly more slim and dense format for downloading an mp4 video and converting from mp4 to mp3:
Download will download the file to the current directory or location of the program, this will also convert the file to mp3 as a NEW file.
from pytube import YouTube
import os
import subprocess
import time
while True:
url = input("URL: ")
# Title and Time
print("...")
print(((YouTube(url)).title), "//", (int(var1)/60),"mins")
print("...")
# Filename specification
# Prevents any errors during conversion due to illegal characters in name
_filename = input("Filename: ")
# Downloading
print("Downloading....")
YouTube(url).streams.first().download(filename=_filename)
time.sleep(1)
# Converting
mp4 = "'%s'.mp4" % _filename
mp3 = "'%s'.mp3" % _filename
ffmpeg = ('ffmpeg -i %s ' % mp4 + mp3)
subprocess.call(ffmpeg, shell=True)
# Completion
print("\nCOMPLETE\n")
This is an infinite loop that will allow the renaming, download, and conversion of multiple URLs.
from pytube import YouTube
yt = YouTube(url)
yt.streams.get_audio_only().download(output_path='/home/',filename=yt.title)
Pytube does not support "mp3" format but you can download audio in webm format. The following code demonstrates it.
from pytube import YouTube
yt = YouTube("https://www.youtube.com/watch?v=kn8ZuOCn6r0")
stream = yt.streams.get_by_itag(251)
stream.download()
For mp3 you have to convert (mp4 or webm) file format to mp3.
This is my solution:
import os
import sys
from pytube import YouTube
from pytube.cli import on_progress
PATH_SAVE = "D:\Downloads"
yt = YouTube("YOUR_URL", on_progress_callback=on_progress)
#Download mp3
audio_file = yt.streams.filter(only_audio=True).first().download(PATH_SAVE)
base, ext = os.path.splitext(audio_file)
new_file = base + '.mp3'
os.rename(audio_file, new_file)
#Download Video
ys = yt.streams.filter(res="1080p").first()
ys.download(PATH_SAVE)
Working: Python v3.9.x and pytube v11.0.1
try to use :
from pytube import YouTube
import os
link = input('enter the link: ')
path = "D:\\" #enter the path where you want to save your video
video = YouTube(link)
print( "title is : ", video.title)
#download video
print("title is : ", video.title)
video.streams.filter(only_audio=True).first().download( path , filename ="TemporaryName.Mp4" )
#remove caracters (" | , / \ ..... ) from video title
VideoTitle = video.title
VideoTitle = VideoTitle.replace('\"' , " ")
VideoTitle = VideoTitle.replace('|', " ")
VideoTitle = VideoTitle.replace(',', " ")
VideoTitle = VideoTitle.replace('/"' , " ")
VideoTitle = VideoTitle.replace('\\', " ")
VideoTitle = VideoTitle.replace(':', " ")
VideoTitle = VideoTitle.replace('*"' , " ")
VideoTitle = VideoTitle.replace('?', " ")
VideoTitle = VideoTitle.replace('<', " ")
VideoTitle = VideoTitle.replace('>"' , " ")
#change name and converting Mp4 to Mp3
my_file = path + "\\" + "TemporaryName.mp4"
base = path + "\\" + VideoTitle
print("New Video Title is :" +VideoTitle)
os.rename(my_file, base + '.mp3')
print(video.title, ' \nhas been successfully downloaded as MP3')
This is my solution:
from os import path, rename
from pytube import YouTube as yt
formato = ""
descarga = desktop = path.expanduser("~/Desktop")
link = input("Inserte el enlace del video: ")
youtube = yt(link)
while formato != "mp3" and formato != "mp4":
formato = input("¿Será en formato mp3 o mp4? ")
if formato == "mp4":
youtube.streams.get_highest_resolution().download(descarga)
elif formato == "mp3":
video = youtube.streams.first()
downloaded_file = video.download(descarga)
base, ext = path.splitext(downloaded_file)
new_file = base + '.mp3'
rename(downloaded_file, new_file)
print("Descarga completa!")
input("Presiona Enter para salir...")
Here is my solution. Just rename downloaded content's name with pytube's filename option.
url = input("URL of the video that will be downloaded as MP^: ")
try:
video = yt(url)
baslik = video.title
print(f"Title: {baslik}")
loc = input("Location: ")
print(f"Getting ITAG info for {baslik}")
for itag in video.streams.filter(only_audio=True): # It'll show only audio streams.
print(itag)
itag = input("ITAG secimi: ")
print(f"{baslik} sesi {loc} konumuna indiriliyor.")
video.streams.get_by_itag(itag).download(loc, filename=baslik + ".mp3") # And you can rename video by filename= option. Just add .mp3 extension to video's title.
print("Download finished.")
except:
print("Enter a valid URL")
sys.exit()
This worked very well for me:
pip install pytube
pip install os_sys
# importing packages
from pytube import YouTube
import os
# url input from user
yt = YouTube(
str(input("paste your link")))
# extract only audio
video = yt.streams.filter(only_audio=True).first()
# check for destination to save file
print("Enter the destination (leave blank for current directory)")
destination = str(input(">> ")) or '.'
# download the file
out_file = video.download(output_path=destination)
# save the file
base, ext = os.path.splitext(out_file)
new_file = base + '.mp3'
os.rename(out_file, new_file)
# result of success
print(yt.title + " has been successfully downloaded.")
Here is the function that downloads music in the highest available quality using pytube and saves it in desired directory.
from pytube import YouTube
import os
from pathlib import Path
def youtube2mp3 (url,outdir):
# url input from user
yt = YouTube(url)
### Extract audio with 160kbps quality from video
video = yt.streams.filter(abr='160kbps').last()
### Downloadthe file
out_file = video.download(output_path=outdir)
base, ext = os.path.splitext(out_file)
new_file = Path(f'{base}.mp3')
os.rename(out_file, new_file)
### Check success of download
if new_file.exists():
print(f'{yt.title} has been successfully downloaded.')
else:
print(f'ERROR: {yt.title}could not be downloaded!')
I have a more Pythonic way to download YouTube videos as MP3 using PyTube:
# Use PyTube to download a YouTube video, then convert to MP3 (if needed) using MoviePy
import pytube
from moviepy.editor import AudioFileClip
link = "your youtube link here"
fn = "myfilename.mp3"
yt = pytube.YouTube(str(link))
video = yt.streams.filter(only_audio=True).first()
out_file = video.download(output_path='.')
os.rename(out_file, fn)
# Check is the file a MP3 file or not
if not out_file.endswith('.mp3'):
# File is not a MP3 file, then try to convert it (first rename it)
dlfn = '.'.join(fn.split('.')[:-1]) + '.' + out_file.split('.')[-1]
os.rename(fn, dlfn)
f = AudioFileClip(dlfn)
f.write_audiofile(fn)
f.close()
os.remove(dlfn)
Code is written in Python3.
Be sure to install the libraries:
python3 -m pip install pytube moviepy
MoviePy dont support every audio files, but it support the most of ones: "empty" mp4 (mp4 that only have music), wav, etc...
Why conversion to MP3 is important ?
A lot of persons just renames the file, but this cannot convert a file ! If you use VLC by example, VLC will play the file not as an MP3, but as the original format. So, if you play the file with a software that only support MP3, the audio player will return an error.
I use python cv2 module to join jpg frames into video, but I can't add audio to it. Is it possible to add audio to video in python without ffmpeg?
P.S. Sorry for my poor English
Use ffpyplayer to handle the audio part.
import cv2
import numpy as np
#ffpyplayer for playing audio
from ffpyplayer.player import MediaPlayer
video_path="../L1/images/Godwin.mp4"
def PlayVideo(video_path):
video=cv2.VideoCapture(video_path)
player = MediaPlayer(video_path)
while True:
grabbed, frame=video.read()
audio_frame, val = player.get_frame()
if not grabbed:
print("End of video")
break
if cv2.waitKey(28) & 0xFF == ord("q"):
break
cv2.imshow("Video", frame)
if val != 'eof' and audio_frame is not None:
#audio
img, t = audio_frame
video.release()
cv2.destroyAllWindows()
PlayVideo(video_path)
The sample code will work but you need to play around the cv2.waitKey(28) depending on the speed of your video.
This is how I am reading audio and video frames:
from moviepy.editor import *
from pafy import pafy
if __name__ == '__main__':
video = pafy.new('https://www.youtube.com/watch?v=K_IR90FthXQ')
stream = video.getbest(preftype='mp4')
video = VideoFileClip(stream.url)
audio = video.audio
for t, video_frame in video.iter_frames(with_times=True):
audio_frame = audio.get_frame(t)
print(audio_frame)
print(video_frame)
This code downloads YouTube video and returns raw frames as numpy arrays.
You can pass the file as an argument to the VideoFileClip instead of the URL.
You can use pygame for audio.
You need to initialize pygame.mixer module
And in the loop, add pygame.mixer.music.play()
But for that, you will need to choose audio file as well.
However, I have found better idea! You can use webbrowser module for playing videos (and because it would play on browser, you can hear sounds!)
import webbrowser
webbrowser.open("video.mp4")
import pygame
pygame.mixer.init()
pygame.mixer.music.load(
'c:Your_file')
pygame.mixer.music.play()
while True:
pygame.time.Clock().tick()
#used to show that you can do other stuff while playing audio
print("hi")