i am trying to write a program to read either mp3 or mp4 music files and then print there tags to the screen but the code i have written dose not seem to work and i am completely lost in now to fix it
# import mutagen
from mutagen.easyid3 import EasyID3
from mutagen.mp4 import MP4
from mutagen.mp3 import MP3
# Define a function to read ID3 tags
MP4 == (audio = MP4(ip))
MP3 == (Audio = MP3(ip))
def readid3 (ip):
if music_file == MP4:
print(audio['\xa9alb'])
print(audio['\xa9nam'])
print(audio['\xa9ART'])
print(audio['\xa9gen'])
else:
if music_file == MP3:
print(audio['TALB'])
print(audio['TIT2'])
print(audio['TPE1'])
print(audio['TCON'])
else:
print('Is not a MP3 or MP4 file')
####### main body ########
# prompt user to enter a MP4
music_file = open('mp4file.txt','a+')
music_file.write("/Users/martins-mac/Music/iTunes/iTunes Media/Music/Frightened Rabbit/Pedestrian Verse/01 Acts of Man.m4a")
music_file.close()
# call function to print ID3 tags
readid3(music_file)
So these two lines
MP4 == (audio = MP4(ip))
MP3 == (Audio = MP3(ip))
Are just comparing something. They'll simply return True or False, and have no effect. As it stands, they're just comparing the modules you've imported to an assignment, which is confusing to me. What were you trying to do with those lines?
if music_file == MP4:
Is the correct way to use ==, but music_file is not defined at this point. When you call it later on, it's defined globally, but it looks like
if ip == MP4:
Would serve you better.
When you get down to readid3(music_file), you've already closed the file. Try putting music_file = open("mp4file.txt", "r") before that line.
You may also be well-served to check out https://mutagen.readthedocs.org/en/latest/api/base.html, as there are bound to be some useable examples in there.
Related
I'm currently working on a project where I request a phone call (Mp3) and have to make an automatic transcript through a python script.
I'm using the Azure Speech to text services and got that all working, but that service only supports a Wav. file and I am still stuck at that part.
import azure.cognitiveservices.speech as speechsdk
import time
from os import path
from pydub import AudioSegment
import requests
import hashlib
OID = ***
string = f"***"
encoded = string.encode()
result = hashlib.sha256(encoded)
resultHash = (result.hexdigest())
r = requests.get(f"***", headers={f"***":f"{***}"})
Telefoongesprek = r
# converts audio file (mp3 to Wav.)
#src = Telefoongesprek
#dst = "Telefoongesprek #****.wav"
#sound = AudioSegment.from_mp3(src)
#sound.export(dst, format="wav")
def speech_recognize_continuous_from_file():
speech_config = speechsdk.SpeechConfig(subscription="***", region="***")
speech_config.speech_recognition_language = "nl-NL"
audio_config = speechsdk.audio.AudioConfig(filename="Telefoongesprek #****.wav")
speech_recognizer = speechsdk.SpeechRecognizer(speech_config=speech_config, audio_config=audio_config)
done = False
def stop_cb(evt):
print('CLOSING on {}'.format(evt))
nonlocal done
done = True
all_results = []
def handle_final_result(evt):
all_results.append(evt.result.text)
#speech_recognizer.recognizing.connect(handle_final_result)
speech_recognizer.recognized.connect(handle_final_result)
speech_recognizer.session_started.connect(handle_final_result)
speech_recognizer.session_stopped.connect(handle_final_result)
speech_recognizer.canceled.connect(handle_final_result)
speech_recognizer.session_stopped.connect(stop_cb)
speech_recognizer.canceled.connect(stop_cb)
speech_recognizer.start_continuous_recognition()
while not done:
time.sleep(.5)
speech_recognizer.stop_continuous_recognition()
print(all_results)
speech_recognize_continuous_from_file()
Thats the code im using without all the keys and encryption, and everthing works apart from the convert from MP3 to Wav.
is there any way I can save the requested file locally in this script and pass it through in:
audio_config = speechsdk.audio.AudioConfig(filename="Telefoongesprek #****.wav"). or do I have to save it to the pc and do it another way.
I have been stuck on this problem for over a week and have tried many different ways.
Thanks in advance!
Beau van der Meer
You should be able to save the response data ( you can access the raw bytes with r.content) to a .mp3 file locally and then pass that file path to pydub.
with open('path/to/local/file.mp3', 'wb') as f:
f.write(r.content)
Another option is to use the module io.BytesIO from the standard library.
If you pass it raw bytes, e g import io; f = io.BytesIO(r.content), it will give you a object that behaves like an open filehandle back, which you can pass to functions accepting files. I didn't check that pydub method you are trying to use accepts filehandles or only paths, so you have to check that first.
My process to achieve, is to print multiple pdf files from a folder, closing Adobe Acrobat afterwards and lastly mapping the files to new folders, using another of my scripts.
The Mapping works as intended, but I´m struggling with printing all files. I can either print only one, or none of the files and Adobe still remains open. I've been playing around with asyncio, but I dont know if it gets the job done.
The code is not very well documented or of outstanding quality, it just has to get the task done and willl be very likely never be touched agein. Here it is:
import os
import sys
import keyboard
import asyncio
import psutil
from win32 import win32api, win32print
import map_files
import utility
def prepareFilesToPrint(folder):
# Scans folder for files with naming convention and puts them in a seperate array to print
filesToPrint = []
for file in os.listdir(folder.value):
if utility.checkFileName(file):
filesToPrint.append(file)
return filesToPrint
def preparePrinter():
# Opens the printer and defines attributes such as duplex mode
name = win32print.GetDefaultPrinter()
printdefaults = {"DesiredAccess": win32print.PRINTER_ALL_ACCESS}
handle = win32print.OpenPrinter(name, printdefaults)
attributes = win32print.GetPrinter(handle, 2)
attributes['pDevMode'].Duplex = 2 # Lange Seite spiegeln
win32print.SetPrinter(handle, 2, attributes, 0)
return handle
async def printFiles(filesToPrint):
for file in filesToPrint:
await win32api.ShellExecute(
0, "print", file, '"%s"' % win32print.GetDefaultPrinter(), ".", 0)
def cleanup(handle):
# Closes Adobe after printing ALL files (!working)
win32print.ClosePrinter(handle)
for p in psutil.process_iter():
if 'AcroRd' in str(p):
p.kill()
async def printTaskFiles():
# Iterates over files in downloads folder and prints them if they are task sheets (!working)
os.chdir("C:/Users/Gebker/Downloads/")
filesToPrint = prepareFilesToPrint(utility.Folder.DOWNLOADS)
if filesToPrint.__len__() == 0:
print("No Files to print. Exiting...")
sys.exit()
print("=============================================================")
print("The following files will be printed:")
for file in filesToPrint:
print(file)
print("=============================================================")
input("Press ENTER to print. Exit with ESC")
while True:
try:
if keyboard.is_pressed('ENTER'):
print("ENTER pressed. Printing...")
handle = preparePrinter()
await printFiles(filesToPrint)
cleanup(handle)
print("Done printing. Mapping files now...")
# map_files.scanFolders()
break
elif keyboard.is_pressed('ESC'):
print("ESC pressed. Exiting...")
sys.exit()
except:
break
if __name__ == "__main__":
asyncio.run(printTaskFiles())
Here is my python code..
import pyttsx3;
engine = pyttsx3.init(driverName='sapi5')
infile = "tanjil.txt"
f = open(infile, 'r')
theText = f.read()
f.close()
engine.say(theText)
engine.runAndWait()
I couldn't save the file to audio file
As of July 14 2019, I'm able to save to file with the pyttsx3 library (without using another library or internet connection).
It doesn't appear to be documented, but looking at the source code in github for the Engine class in "engine.py" (https://github.com/nateshmbhat/pyttsx3/blob/master/pyttsx3/engine.py), I was able to find a "save_to_file" function:
def save_to_file(self, text, filename, name=None):
'''
Adds an utterance to speak to the event queue.
#param text: Text to sepak
#type text: unicode
#param filename: the name of file to save.
#param name: Name to associate with this utterance. Included in
notifications about this utterance.
#type name: str
'''
self.proxy.save_to_file(text, filename, name)
I am able to use this like:
engine.save_to_file('the text I want to save as audio', path_to_save)
Not sure the format - it's some raw audio format (I guess it's maybe something like aiff) - but I can play it in an audio player.
If you install pydub:
https://pypi.org/project/pydub/
then you can easily convert this to mp3, e.g.:
from pydub import AudioSegment
AudioSegment.from_file(path_to_save).export('converted.mp3', format="mp3")
I've tried #Brian's solution but it didn't work for me.
I searched around a bit and I couldn't figure out how to save the speech to mp3 in pyttx3 but I found another solution without pyttx3.
It can take a .txt file and directly output a .wav file,
def txt_zu_wav(eingabe, ausgabe, text_aus_datei = True, geschwindigkeit = 2, Stimmenname = "Zira"):
from comtypes.client import CreateObject
engine = CreateObject("SAPI.SpVoice")
engine.rate = geschwindigkeit # von -10 bis 10
for stimme in engine.GetVoices():
if stimme.GetDescription().find(Stimmenname) >= 0:
engine.Voice = stimme
break
else:
print("Fehler Stimme nicht gefunden -> Standard wird benutzt")
if text_aus_datei:
datei = open(eingabe, 'r')
text = datei.read()
datei.close()
else:
text = eingabe
stream = CreateObject("SAPI.SpFileStream")
from comtypes.gen import SpeechLib
stream.Open(ausgabe, SpeechLib.SSFMCreateForWrite)
engine.AudioOutputStream = stream
engine.speak(text)
stream.Close()
txt_zu_wav("test.txt", "test_1.wav")
txt_zu_wav("It also works with a string instead of a file path", "test_2.wav", False)
This was tested with Python 3.7.4 on Windows 10.
import pyttsx3
engine = pyttsx3.init("sapi5")
voices = engine.getProperty("voices")[0]
engine.setProperty('voice', voices)
text = 'Your Text'
engine.save_to_file(text, 'name.mp3')
engine.runAndWait() # don't forget to use this line
Try the following code snippet to convert text to audio and save it as an mp3 file.
import pyttsx3
from pydub import AudioSegment
engine = pyttsx3.init('sapi5')
engine.save_to_file('This is a test phrase.', 'test.mp3') # raw audio file
engine.runAndWait()
AudioSegment.from_file('test.mp3').export('test.mp3', format="mp3") # audio file in mp3 format
NB: pyttsx3 save_to_file() method creates a raw audio file and it won't be useful for other applications to use even if we are able to play it in the media player. pydub is a useful package to convert raw audio into a specific format.
I'm using youtube-dl in a Python program as a module and not from the command line. It works just fine except for when I download (ironically) some YouTube videos - specifically, the ones where the audio is encoded as a separate file from the video. Basically, I need the name of the final file, however I get the names of the two files before remuxing. According to the youtube-dl documentation, you can get the final filename using hooks:
filename: The final filename (always present)
tmpfilename: The filename we're currently writing to
seems 'filename' should get me the name of the file that is created from the audio and video that was downloaded and combined. But it does not do that.
here is my code:
def my_hook(d):
if d['status'] == 'finished':
print "\nYour video has been downloaded!"
filelocation = d['filename']
print filelocation
def download_video(url, archival_location, asset):
global mountpoint
# Put Location and filename to save in a variable
destination = archival_location + asset + ".%(ext)s"
# options for youtubedl
ydl_opts = {
'logger' : MyLogger(),
'progress_hooks': [my_hook],
'outtmpl' : destination
}
try:
# Lets download it now
with YoutubeDL(ydl_opts) as ydl:
ydl.download([url])
print ""
except:
print "Error with downloader. Most likely Unsupported URL"
#check and see if we mounted a drive
if mounted:
unmount(mountpoint)
# Exit the program
exit()
There is more to the program but this is the pertinent bit. Here is the output when downloading a video from YouTube:
Your video has been downloaded!
/Volumes/RR261-GOING-POSTAL_1/RR261_Archival_Footage/RR261_A999_Erase_Please.f243.webm
Your video has been downloaded!
/Volumes/RR261-GOING-POSTAL_1/RR261_Archival_Footage/RR261_A999_Erase_Please.f141.m4a
Now my program will fail because the variable filelocation points to the m4a file that will be gone once ffmpeg does its thing. How do I get youtube-dl to report the final file? Or am I going about this the wrong way? Is there another way to get the path and filename of what ffmpeg has created? My program doesn't call ffmpeg, the youtube-dl module does, and I don't see what it's doing from stdout.
The Problem:
I have been playing around with CherryPy for the past couple of days but I'm still having some trouble with getting images to work how I could expect them to. I can save an uploaded image as a jpg without issue but I can't convert it to a base64 image properly. Here's the simple server I wrote:
server.py
#server.py
import os
import cherrypy #Import framework
frameNumber = 1
lastFrame = ''
lastFrameBase64 = ''
class Root (object):
def upload(self, myFile, username, password):
global frameNumber
global lastFrameBase64
global lastFrame
size = 0
lastFrameBase64 = ''
lastFrame = ''
while True:
data = myFile.file.read(8192)
if not data:
break
size += len(data)
lastFrame += data
lastFrameBase64 += data.encode('base64').replace('\n','')
f = open('/Users/brian/Files/git-repos/learning-cherrypy/tmp_image/lastframe.jpg','w')
f.write(lastFrame)
f.close()
f = open('/Users/brian/Files/git-repos/learning-cherrypy/tmp_image/lastframe.txt','w')
f.write(lastFrameBase64)
f.close()
cherrypy.response.headers['Content-Type'] = 'application/json'
print "Image received!"
frameNumber = frameNumber + 1
out = "{\"status\":\"%s\"}"
return out % ( "ok" )
upload.exposed = True
cherrypy.config.update({'server.socket_host': '192.168.1.14',
'server.socket_port': 8080,
})
if __name__ == '__main__':
# CherryPy always starts with app.root when trying to map request URIs
# to objects, so we need to mount a request handler root. A request
# to '/' will be mapped to HelloWorld().index().
cherrypy.quickstart(Root())
When I view the lastframe.jpg file, the image renders perfectly. However, when I take the text string found in lastframe.txt and prepend the proper data-uri identifier data:image/jpeg;base64, to the base64 string, I get a broken image icon in the webpage I'm trying to show the image in.
<!DOCTYPE>
<html>
<head>
<title>Title</title>
</head>
<body>
<img src="data:image/jpeg;base64,/9....." >
</body>
</html>
I have tried using another script to convert my already-saved jpg image into a data-uri and it works. I'm not sure what I'm doing wrong in the server example b/c this code gives me a string that works as a data-uri:
Working Conversion
jpgtxt = open('tmp_image/lastframe.jpg','rb').read().encode('base64').replace('\n','')
f = open("jpg1_b64.txt", "w")
f.write(jpgtxt)
f.close()
So basically it comes down to how is the data variable taken from myFile.file.read(8192) is different from the data variable taken from open('tmp_image/lastframe.jpg','rb') I read that the rb mode in the open method tells python to read the file as a binary file rather than a string. Here's where I got that.
Summary
In summary, I don't know enough about python or the cherrypy framework to see how the actual data is stored when reading from the myFile variable and how the data is store when reading from the output of the open() method. Thanks for taking the time to look at this problem.
Base64 works by taking every 3 bytes of input and producing 4 characters. But what happens when the input isn't a multiple of 3 bytes? There's special processing for that, appending = signs to the end. But that's only supposed to happen at the end of the file, not in the middle. Since you're reading 8192 bytes at a time and encoding them, and 8192 is not a multiple of 3, you're generating corrupt output.
Try reading 8190 bytes instead, or read and encode the entire file at once.