I have a .m3u8 link which I'm trying to download as an .mp3 file.
import m3u8
import subprocess
import requests
link = 'https://cs9-9v4.vkuseraudio.net/s/v1/ac/NeMmHNX2Iyt08MZ4z5fELAMybgSNR6T1xYEcBEv5Kdsenci3KHOAC-1fKapAV9vxwVOBIik40I4DwfrN-a_jtjILYVcx3mLTNCzKo1UF-UhbKOztLrboF9NEn1jzZs1Jl0ijfmccog6aAcB4PcdnrxPzXY7WCMVWtUjWKOgHad5a-g0/index.m3u8'
m3u8_parsed = m3u8.load(link)
with open('track.ts', 'wb') as f:
for segment in m3u8_parsed.segments:
r = requests.get(segment.absolute_uri)
f.write(r.content)
subprocess.run(['ffmpeg', '-i', 'track.ts', 'track.mp3'])
The result is that the track.ts file takes up 6MB storage but doesn't have sound when I try to play it with the VLC Player, while track.mp3 is basically an empty file taking up a couple kilobytes.
You only need FFmpeg to retrieve the audio:
import subprocess
link = 'https://cs9-9v4.vkuseraudio.net/s/v1/ac/NeMmHNX2Iyt08MZ4z5fELAMybgSNR6T1xYEcBEv5Kdsenci3KHOAC-1fKapAV9vxwVOBIik40I4DwfrN-a_jtjILYVcx3mLTNCzKo1UF-UhbKOztLrboF9NEn1jzZs1Jl0ijfmccog6aAcB4PcdnrxPzXY7WCMVWtUjWKOgHad5a-g0/index.m3u8'
subprocess.run(['ffmpeg', '-i', link, 'track.mp3'])
This resulted in a playable mp3 file when I tried it.
Related
I've downloaded some files using requests
url = 'https://www.youtube.com/watch?v=gp5tziO5lXg&feature=youtu.be'
video_name = url.split('/')[-1]
print("Downloading file:%s" % video_name)
# download the url contents in binary format
r = requests.get(url)
# open method to open a file on your system and write the contents
with open('saved.mp4', 'wb') as f:
f.write(r.content)
and using urllib.requests
url = 'https://www.youtube.com/watch?v=gp5tziO5lXg&feature=youtu.be'
video_name = url.split('/')[-1]
print("Downloading file:%s" % video_name)
# Copy a network object to a local file
urllib.request.urlretrieve(url, "saved2.mp4")
When I then try to open the .mp4 file I get the following error
Cannot play
This file cannot be played. This can happen because the file type is
not supported, the file extension is incorrect or the file is
corrupted.
0xc00d36c4
If I test it with pytube it works fine.
What's wrong with the other methods?
To answer your question, with the other methods it is not downloading the video but the page. What you may be obtaining is an html file with an mp4 file extension.
Therefore, it gives that error when trying to open the file.
If pytube works for what you need, I would suggest using that one.
If you want to download videos from other platforms, you might consider youtube-dl.
Hello you can import IPython.display for audio diplay
import IPython.display as ipd
ipd.Audio(video_name)
regards
I hope I can have solved your problem
I created script which one downloading video and sound from Youtube, and after that merging sound and video with ffmpeg, i wondering is another way to make same result but in faster way? Because this script takes about 7 min ~ depends on Video quality and duration. My code bellow:
from pytube import YouTube
import sys
import ffmpeg
import os
class Downloader(YouTube):
def __init__(self, link):
self.link = YouTube(link)
self.hq = []
self.best_video = []
self.best_sound = []
def stream_objects(self):
q = [self.hq.append(x) for x in self.link.streams.all()]
self.best_video.append(str(self.hq[1]).split()[1].split('\"')[1])
self.best_sound.append(str(self.hq[-1]).split()[1].split('\"')[1])
return self.best_video, self.best_sound
def downloady(self):
vid = self.link.streams.get_by_itag(str(self.best_video).strip("['']"))
audio = self.link.streams.get_by_itag(str(self.best_sound).strip("['']"))
self.vid_title = (f"{vid.title}"+".mp4")
vid.download(filename='video')
audio.download(filename='audio')
print('Downloaded, Now Starting Merge \n\n\n\n\n')
print(f'{self.vid_title}'+'\n')
def merge(self):
ffmpeg.output(ffmpeg.input('video.mp4'), ffmpeg.input('audio.webm'), self.vid_title).run()
os.remove('video.mp4')
os.remove('audio.webm')
if __name__=='__main__':
a = Downloader(link = sys.argv[1])
a.stream_objects()
a.downloady()
a.merge()
OKE UPDATE:
Now code looks like that..Second problem is slow downloading mp4 files from YouTube server, i have 10Gb/s internet. Good connection with YT servers, but why so poor downloading ? ? ? :)
from pytube import YouTube
import sys
import ffmpeg
import os
import subprocess
class Downloader(YouTube):
def __init__(self, link):
self.link = YouTube(link)
self.hq = []
def stream_objects(self):
self.best = self.link.streams.filter(file_extension='mp4')
q = [self.hq.append(x) for x in self.best.all()]
self.best_vid_itag = str(self.best.all()[1]).split()[1].split('\"')[1]
self.best_audio_itag = str(self.best.all()[-1]).split()[1].split('\"')[1]
def downloader(self):
vid = self.link.streams.get_by_itag(self.best_vid_itag)
aud = self.link.streams.get_by_itag(self.best_audio_itag)
print('Donwloading Video file...\n')
vid.download(filename='video')
print('Video file downloaded... Now Trying download Audio file..\n')
aud.download(filename='audio')
print('Audio file downloaded... Now Trying to merge audio and video files...\n')
def merger(self):
lin = str(self.link.title).rstrip()
lin2 = (lin+'.mp4')
subprocess.run(f'ffmpeg -i video.mp4 -i audio.mp4 -c copy "{lin2}"', shell=True)
os.remove('video.mp4')
os.remove('audio.mp4')
print('Done....\n')
if __name__=='__main__':
a = Downloader(link = sys.argv[1])
a.stream_objects()
a.downloader()
a.merger()
First of all you download a video file and audio file with different encoding
In your case it is mp4 and webm
You should for example download an mp4 video and m4a audio
Or a webm video and a webm audio
Then it comes to ffmpeg, you should pass a parameter “-c copy”
Example for ffmpeg comand line:
ffmpeg -i myvideo.mp4 -i myaudio.m4a -c copy output.mp4
Here is a link to a python project on github use same technique
https://github.com/pyIDM/pyIDM
Check video.py file
Further explanation:
When you use “-c copy” parameter, ffmpeg will just copy the audio track and merge it with video provided that both audio and video has same codec container, this process take less than 2 seconds
Otherwise it will process every frame in video and every bit in audio then convert them to a desired format, which takes very long time
I have a video file named 'video.mp4'. I am trying to seperate a section of audio from the video and save it as a wav file that can be used with other Python modules. I want to do this with MoviePy.
I send parameters to the write_audiofile function, specifying the filename, fps, nbyte, and codec.
Following the MoviePy AudioClip docs, I specified the codec as ‘pcm_s32le’ for a 32-bit wav file.
from moviepy.editor import *
sound = AudioFileClip("video.mp4")
newsound = sound.subclip("00:00:13","00:00:15") #audio from 13 to 15 seconds
newsound.write_audiofile("sound.wav", 44100, 2, 2000,"pcm_s32le")
This code generates a .wav file, named 'sound.wav'.
Opening the audio file in Audacity
The resulting file, sound.wav, can be opened in Audacity, however I run into problems when I try to use it as a wav file with other Python modules.
Playing the sound file in pygame
import pygame
pygame.mixer.init()
sound=pygame.mixer.Sound("sound.wav")
The third line gives the following error:
pygame.error: Unable to open file 'sound.wav'
Determining type of sound file using sndhdr.what()
import sndhdr
sndhdr.what("sound.wav")
The sndhdr method returned none
. According to the docs, when this happens, the method failed to determine the type of sound data stored in the file.
Reading the file with Google Speech Recognition
import speech_recognition as sr
r = sr.Recognizer()
audio = "sound.wav"
with sr.AudioFile(audio) as source:
audio = r.record(source)
text= r.recognize_google(audio)
print(text)
This code stops execution on the second to last line:
ValueError: Audio file could not be read as PCM WAV, AIFF/AIFF-C, or Native FLAC; check if file is corrupted or in another format
Why does the audio file open in Audacity, if sndhdr.what() can not recognize it as an audio file type?
How can I properly export a MoviePy AudioClip as a wav file?
I had the same issue with no codec specified or with codec = 'pcms32le', the one that worked for me was pcm_s16le.
Note that I am using "fr-FR" language, you should probably adapt to yur needs.
here is the entire code :
# Python code to convert video to audio
import moviepy.editor as mp
import speech_recognition as sr
# Insert Local Video File Path
clip = mp.VideoFileClip("/tmp/data/test.mp4")
# Insert Local Audio File Path
clip.audio.write_audiofile("/tmp/data/test.wav",codec='pcm_s16le')
# initialize the recognizer
r = sr.Recognizer()
# open the file
with sr.AudioFile("/tmp/data/test.wav") as source:
# listen for the data (load audio to memory)
audio_data = r.record(source)
# recognize (convert from speech to text)
text = r.recognize_google(audio_data, language = "fr-FR")
print(text)
I had the same issue. I was trying to get a mp4 file from URL, then convert It into wav file and call Google Speech Recognition over It. Instead I used pydub to handle conversion and it worked! Here's a sample of the code:
import requests
import io
import speech_recognition as sr
from pydub import AudioSegment
# This function translate speech to text
def speech_to_text(file):
recognizer = sr.Recognizer()
audio = sr.AudioFile(file)
with audio as source:
speech = recognizer.record(source)
try:
# Call recognizer with audio and language
text = recognizer.recognize_google(speech, language='pt-BR')
print("Você disse: " + text)
return text
# If recognizer don't understand
except:
print("Não entendi")
def mp4_to_wav(file):
audio = AudioSegment.from_file(file, format="mp4")
audio.export("audio.wav", format="wav")
return audio
def mp4_to_wav_mem(file):
audio = AudioSegment.from_file_using_temporary_files(file, 'mp4')
file = io.BytesIO()
file = audio.export(file, format="wav")
file.seek(0)
return file
url = ''
r = requests.get(url, stream=True)
file = io.BytesIO(r.content)
file = mp4_to_wav_mem(file)
speech_to_text(file)
Note that I wrote two functions: mp4_to_wav and mp4_to_wav_mem. The only difference is mp4_to_wav_mem handle all files in memory and mp4_to_wav generates .wav file.
I read the docs of MoviePy and found that the parameter nbyte should be consistent with codec. nbyte is for the Sample width (set to 2 for 16-bit sound, 4 for 32-bit sound). Hence, it better set nbyte=4, when you set codec=pcm_s32le.
i think this is the right method:
import os
from moviepy.editor import AudioFileClip
PATH= "files/"
fileName = "nameOfYourFile.mp4"
newFileName = "nameOfTheNewFile"
Ext = "wav"
AudioFileClip(os.path.join(PATH, f"{fileName}")).write_audiofile(os.path.join(PATH, f"{newFileName}.{Ext}"))
I think this approach is very easy to understand.
from moviepy.editor import *
input_file = "../Database/myvoice.mp4"
output_file = "../Database/myvoice.wav"
sound = AudioFileClip(input_file)
sound.write_audiofile(output_file, 44100, 2, 2000,"pcm_s32le")
When I concatenate videos in Moviepy I get no sound in the output file, I try using various parameters but no clue.
This is my code:
import moviepy.editor as mp
import os
dir_path = os.path.dirname(os.path.realpath(__file__))
clip1 = mp.VideoFileClip("V1.mp4")
clip2 = mp.VideoFileClip(dir_path+"\\V2.mp4")
clip3 = mp.VideoFileClip(dir_path+"\\V3.mp4")
output_movie = 'new_movie1.mp4'
final_clip = mp.concatenate_videoclips([clip1,clip2,clip3])
final_clip.write_videofile(output_movie, remove_temp=False, bitrate="5000k",audio=True, audio_codec="aac",codec='mpeg4')
I tried codec="libx264"
I solved this by adding a temporary audio file path. Just change your final line of code to this:
final_clip.write_videofile(output_movie, temp_audiofile='temp-audio.m4a', remove_temp=True, codec="libx264", audio_codec="aac")
You're specifying where MoviePy can store its temp audio file. Also, change the parameter remove_temp to True so the temp file will be cleaned up automatically.
I solved this through a workaround using ffmpeg directly. It uses the temp audio file and video file from moviepy to create a final file. I found that moviepy 1.0.1 does not call ffmpeg with the right arguments to combine the video and audio for mp4 video. This link helped me with ffmpeg:https://superuser.com/questions/277642/how-to-merge-audio-and-video-file-in-ffmpeg
final_clip.write_videofile(moviepy_outfile, temp_audiofile=temp_audiofile,codec="libx264",remove_temp=False,audio_codec='aac')
import subprocess as sp
command = ['ffmpeg',
'-y', #approve output file overwite
'-i', str(moviepy_outfile),
'-i', str(temp_audiofile),
'-c:v', 'copy',
'-c:a', 'copy',
'-shortest',
str(output_movie) ]
with open(ffmpeg_log, 'w') as f:
process = sp.Popen(command, stderr=f)
I'm trying to find a simple way to send an MP3 to Google for speech recognition. Currently, I'm using a sub process to call SoX which converts it to a WAV. Then, using SpeechRecognition, it converts it again to FLAC. Ideally, I'd like a more portable (not OS specific) way to decode the MP3 and send it with no intermediate file saving and the like.
Here's what I have currently:
import speech_recognition as sr
import subprocess
import requests
audio = requests.get('http://somesite.com/some.mp3')
with open('/tmp/audio.mp3', 'wb') as file:
file.write(audio.content)
subprocess.run(['sox', '/tmp/audio.mp3', '/tmp/audio.wav'])
r = sr.Recognizer()
with sr.WavFile('/tmp/audio.wav') as source:
audio = r.record(source)
result = r.recognize_google(audio)
del r
I've tried directly using the FLAC binaries included in SpeechRecognition, but the output was just static. I'm not too keen on distributing binaries on Git, but I will if that is the only way.
Some important links:
SR's code for speech recognition
SR's code for WAV to FLAC
Edit
I'm considering distributing SoX in a way like the FLAC binaries were, one for each OS, if SoX's license allows it...
Second thought, software licenses are confusing and I don't want to mess with that.
I decided to go with this:
import subprocess
import requests
import shutil
import glob
import json
audio = requests.get('http://somesite.com/some.mp3')
sox = shutil.which('sox') or glob.glob('C:\Program Files*\sox*\sox.exe')[0]
p = subprocess.Popen(sox + ' -t mp3 - -t flac - rate 16k', stdin = subprocess.PIPE, stdout = subprocess.PIPE, shell = True)
stdout, stderr = p.communicate(audio.content)
url = 'http://www.google.com/speech-api/v2/recognize?client=chromium&lang=en-US&key=AIzaSyBOti4mM-6x9WDnZIjIeyEU21OpBXqWBgw'
headers = {'Content-Type': 'audio/x-flac; rate=16000'}
response = requests.post(url, data = stdout, headers = headers).text
result = None
for line in response.split('\n'):
try:
result = json.loads(line)['result'][0]['alternative'][0]['transcript']
break
except:
pass
This is more of a middle ground I suppose borrowing some stuff from the SR module. It would require the user to install SoX, but should work on all OS and doesn't have any intermediate files. I have only tested it on Linux however.