Consume Flask video streaming with ffmpeg - python-3.x

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!

Related

No sound in video downloaded from youtube using pytube

I'm able to download the video using "pytube" library but, the downloaded video has no sound in playback!
Here's what I've tried...
"""
Developer: #skywalkerSam
Aim: To download youtube videos...
Date: 12022.07.13.03:00
"""
from pytube import YouTube
yt = YouTube("https://www.youtube.com/watch?v=kJQP7kiw5Fk", use_oauth=True, allow_oauth_cache=True)
def info():
print("\nTitle: ", yt.title)
print("Views: ", yt.views)
# print("Description: \t", yt.description)
print("Thumbnail: ", yt.thumbnail_url)
print('Stream Options: \n', yt.streams.filter().order_by('resolution').desc(), '\n')
def download():
yt.streams.filter(progressive=True)
stream = yt.streams.get_by_itag(399)
print("\nProcessing Your Request, Please Wait...\n")
stream.download(output_path="C:\\Users\\samsk\\Downloads\\Youtube\\")
print("\nDownload Complete :) \n")
if __name__ == "__main__":
try:
info()
download()
except KeyboardInterrupt:
print("\n\n Operation Cancelled By User :( \n")
exit()
except Exception as e:
print("\nError: ", e)
Please help me with this, Thank You...
You must download the audio and video to combine the two
I did it with moviepy:
import moviepy.editor as mpe
vname = "clip.mp4"
aname = "audio.mp3"
# Download video and rename
video = pytube.YouTube(url).streams.filter(subtype='mp4', res="1080p").first().download()
os.rename(video, vname)
# Download audio and rename
audio = pytube.YouTube(url).streams.filter(only_audio=True).first().download()
os.rename(audio, aname)
# Setting the audio to the video
video = mpe.VideoFileClip(vname)
audio = mpe.AudioFileClip(aname)
final = video.set_audio(audio)
# Output result
final.write_videofile("video.mp4")
# Delete video and audio to keep the result
os.remove(vname)
os.remove(aname)
Here's a working script to download videos from youtube, install required modules on your system, and change youtube URLs (if you want) and You're good to go
import moviepy.editor as mpe
import os
import pytube
vname = "clip.mp4"
aname = "audio.mp3"
# Download video and rename
video = pytube.YouTube("https://www.youtube.com/watch?v=kJQP7kiw5Fk").streams.filter(
subtype='mp4', res="1080p").first().download()
os.rename(video, vname)
# Download audio and rename
audio = pytube.YouTube(
"https://www.youtube.com/watch?v=kJQP7kiw5Fk").streams.filter(only_audio=True).first().download()
os.rename(audio, aname)
# Setting the audio to the video
video = mpe.VideoFileClip(vname)
audio = mpe.AudioFileClip(aname)
final = video.set_audio(audio)
# Output result
final.write_videofile("video.mp4")
# Delete video and audio to keep the result
os.remove(vname)
os.remove(aname)
Takes a bit of time to compile audio & video together. So, give it some time...

RTSP video change with python scheduler

I have 2 RTSP streams, I would like to change between them each minute and I would like to write the result into the same file (streaming.m3u8) and I would like embed HTML video tag.
But the video change is not working.
import ffmpeg
import schedule
import time
def stream_1():
packet_size = 4096
process = (
ffmpeg
.input('rtsp://....')
.output('streaming.m3u8', hls_time=3, hls_wrap=10)
.run_async(pipe_stdout=True)
)
while process.poll() is None:
packet = process.stdout.read(packet_size)
try:
tcp_socket.send(packet)
except socket.error:
process.stdout.close()
process.wait()
break
def stream_2():
packet_size = 4096
process = (
ffmpeg
.input('rtsp://....')
.output('streaming.m3u8', hls_time=3, hls_wrap=10)
.run_async(pipe_stdout=True)
)
while process.poll() is None:
packet = process.stdout.read(packet_size)
try:
tcp_socket.send(packet)
except socket.error:
process.stdout.close()
process.wait()
break
schedule.every(1).minutes.do(stream_1)
schedule.every(2).minutes.do(stream_2)

With Google Cloud Function creating thumbnail of video with sub dir path

I am uploading Videos by rest api into google Cloud bucket and add one function to generate thumbnail with python. Code working on main directory but my video's uploaded in sub/sub/ directory so my code is not working.
import os
from google.cloud import storage
from subprocess import check_output
from videoprops import get_video_properties
client = storage.Client()
def hello_gcs(data, context):
print(context)
print(data)
if data['contentType'].startswith('video/'):
bucket = client.get_bucket(data['bucket'])
name = data['name']
file_name = '/tmp/'+ name
print(file_name)
thumbnail_file_name = '/tmp/' + name.split('.')[0] + '.jpg'
print(thumbnail_file_name)
try:
os.remove(file_name)
except OSError:
pass
try:
os.remove(thumbnail_file_name)
except OSError:
pass
print("File has been removed")
blob = bucket.get_blob(name)
blob.download_to_filename(file_name)
print("Video Downloaded")
props = get_video_properties(file_name)
if os.path.exists(file_name):
print("NEW MP4 EXISTS")
check_output('ffmpeg -itsoffset -4 -i '+file_name+' -vcodec mjpeg -vframes 1 -an -f rawvideo -s '+str(props['width'])+'x'+str(props['height'])+' '+thumbnail_file_name, shell=True)
thumbnail_blob = bucket.blob('thumbnail.jpg')
thumbnail_blob.upload_from_filename(thumbnail_file_name)
else:
print("MP4 not created")
print("uploaded")
else :
print("Not a Video")
So im only accessing tmp but not able to create folder like /tmp/Upload/Video/232/video.mp4.
Thanks
Dharmesh
Here my code for sub dir videos can generate thumbnail and upload in same dir.
import os
from google.cloud import storage
from subprocess import check_output
from videoprops import get_video_properties
client = storage.Client()
def hello_gcs(data, context):
print(context)
print(data)
if data['contentType'].startswith('video/'):
bucket = client.get_bucket(data['bucket'])
name = data['name']
os.makedirs('/tmp/'+os.path.dirname(name), exist_ok=True)
file_name = '/tmp/'+ name
print(file_name)
thumbnail_file_name = '/tmp/' + name.split('.')[0] + '.jpg'
print(thumbnail_file_name)
try:
os.remove(file_name)
except OSError:
pass
try:
os.remove(thumbnail_file_name)
except OSError:
pass
print("File has been removed")
blob = bucket.get_blob(name)
blob.download_to_filename(file_name)
print("Video Downloaded")
props = get_video_properties(file_name)
if os.path.exists(file_name):
print("NEW MP4 EXISTS")
check_output('ffmpeg -itsoffset -4 -i '+file_name+' -vcodec mjpeg -vframes 1 -an -f rawvideo -s '+str(props['width'])+'x'+str(props['height'])+' '+thumbnail_file_name, shell=True)
thumbnail_blob = bucket.blob(os.path.dirname(name)+'/thumbnail.jpg')
thumbnail_blob.upload_from_filename(thumbnail_file_name)
else:
print("MP4 not created")
print("uploaded")
else :
print("Not a Video")
Requirement.txt
google-cloud-storage
get-video-properties

Audio to text is slow and words are getting dropped

I have a code which takes videos from an input folder, converts it into audio file(.wav) using ffmpeg.
It then converts the audio file to text by recording 30 seconds audio (dura=30) and converting it to text using google translate api.
The problem is that the code takes a lot of time to convert video to text and it drops first two words and some words after every 30 seconds.
import speech_recognition as sr
import sys
import shutil
from googletrans import Translator
from pathlib import Path
import os
import wave
def audio_to_text(self,video_lst,deploy_path,video_path,audio_path):
try:
txt_lst=[]
for video_file in video_lst:
file_part=video_file.split('.')
audio_path_mod = audio_path +'/'+ '.'.join(file_part[:-1])
dir_path=video_path+'.'.join(file_part[:-1])
self.createDirectory(audio_path_mod)
audio_file='.'.join(file_part[:-1])+'.wav'
command_ffmpeg='set PATH=%PATH%;'+deploy_path.replace('config','script')+'audio_video/ffmpeg/bin/'
command='ffmpeg -i '+video_path+'/'+video_file+' '+audio_path_mod+'/'+audio_file
os.system(command_ffmpeg)
os.system(command)
r=sr.Recognizer()
dura=30
lang='en'
wav_filename=audio_path_mod+'/'+audio_file
f = wave.open(wav_filename, 'r')
frames = f.getnframes()
rate = f.getframerate()
audio_duration = frames / float(rate)
final_text_lst=[]
counter=0
with sr.AudioFile(wav_filename) as source:
while counter<audio_duration:
audio=r.record(source,duration=dura)
counter+=dura
try:
str=r.recognize_google(audio)
final_text_lst.append(str)
except Exception as e:
print(e)
print('Text data generated..')
text_path=audio_path_mod+'/'+audio_file.replace('.wav','_audio_text.csv')
with open(text_path, 'w') as f:
f.write(' '.join(final_text_lst))
except Exception as e:
print(e)
Any help/suggestion would be valuable. Thanks in advance.

Download video in mp3 format using pytube

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.

Resources