Trying to iterate through .wav files in a directory (Python)
It seems that you're just not running your code in the wav directory. listdir
just return the filename, not the whole path, you need to join with the directory
p1 = AudioSegment.from_wav(os.path.join(directory, filename))
Python: Create a list of directories containing audio files
from glob import glob
list_subfolders_with_paths = glob('path/*.mp3')
Replace mp3 with audio files extensions and * is for every mp3 file in path.
JAVA - iterate through a folder of audio files, concatenating another audio file to each one
The error
AudioInputStream clip1 = AudioSystem.getAudioInputStream(new File(f.getName()));
This tries to create a file with the given file name, and looks for it in the current directory.
You should be using File.getAbsolutePath() to get the full absolute path to the file
AudioInputStream clip1 = AudioSystem.getAudioInputStream(new File(f.getAbsolutePath()));
or more simply
AudioInputStream clip1 = AudioSystem.getAudioInputStream(f);
Same problem with wavFile2
I suspect you will have the same issue with the second file:
AudioInputStream clip2 = AudioSystem.getAudioInputStream(new File(wavFile2));
You will need to provide an absolute path here too. If it also is in the audDir
then do
File wavFile2 = new File(audDir.getAbsolutePath() + "/silence_2sec.wav");
AudioInputStream clip2 = AudioSystem.getAudioInputStream(wavFile2);
Iterating over .wav files in subdirectories of parent directory
Edit: If you want an example for glob (more sane), here it is:
from pathlib import Path
# The pattern "**" means all subdirectories recursively,
# with "*.wav" meaning all files with any name ending in ".wav".
for file in Path(data_path).glob("**/*.wav"):
if not file.is_file(): # Skip directories
continue
with open(file, "w") as f:
# do stuff
For more info see Path.glob()
on the documentation. Glob patterns are a useful thing to know.
Previous answer:
Try using either glob or os.walk()
. Here is an example for os.walk()
.
from os import walk, path
# Recursively walk the directory data_path
for root, _, files in walk(data_path):
# files is a list of files in the current root, so iterate them
for file in files:
# Skip the file if it is not *.wav
if not file.endswith(".wav"):
continue
# os.path.join() will create the path for the file
file = path.join(root, files)
# Do what you need with the file
# You can also use block context to open the files like this
with open(file, "w") as f: # "w" means permission to write. If reading, use "r"
# Do stuff
Note that you may be confused about what open()
does. It opens a file for reading, writing, and appending. Directories are not files, and therefore cannot be opened.
I suggest that you Google for documentation and do more reading about the functions used. The documentation will help more than I can.
Another good answer explaining in more detail can be seen here.
Loop of function for taking multiple audio files from a directory
You can get all files of a directory and subdirectory with os.walk
, which I have included in the get_file_paths()
in the code below, here is an example:
import speech_recognition as sr
import csv
import os
DIRNAME = r'c:\path\to\directory'
OUTPUTFILE = r'c:\path\to\outputfiledir\outputfile.csv'
def get_file_paths(dirname):
file_paths = []
for root, directories, files in os.walk(dirname):
for filename in files:
filepath = os.path.join(root, filename)
file_paths.append(filepath)
return file_paths
def process_file(file):
r = sr.Recognizer()
a = ''
with sr.AudioFile(file) as source:
audio = r.record(source)
try:
a = r.recognize_google(audio)
except sr.UnknownValueError:
a = "Google Speech Recognition could not understand audio"
except sr.RequestError as e:
a = "Could not request results from Google Speech Recognition service; {0}".format(e)
return a
def main():
files = get_file_paths(DIRNAME) # get all file-paths of all files in dirname and subdirectories
for file in files: # execute for each file
(filepath, ext) = os.path.splitext(file) # get the file extension
file_name = os.path.basename(file) # get the basename for writing to output file
if ext == '.wav': # only interested if extension is '.wav'
a = process_file(file) # result is returned to a
with open(OUTPUTFILE, 'a') as f: # write results to file
writer = csv.writer(f)
writer.writerow(['file_name','google'])
writer.writerow([file_name, a])
if __name__ == '__main__':
main()
If you want to do multiple recognizers, something like this could work. Please note this is an untested example:
import speech_recognition as sr
import csv
import os
DIRNAME = r'c:\path\to\directory'
OUTPUTFILE = r'c:\path\to\outputfiledir\outputfile.csv'
def get_file_paths(dirname):
file_paths = []
for root, directories, files in os.walk(dirname):
for filename in files:
filepath = os.path.join(root, filename)
file_paths.append(filepath)
return file_paths
def recog_multiple(file):
r = sr.Recognizer()
r_types = ['recognize_google', 'recognize_sphinx']
results = []
for r_type in r_types:
result = ''
with sr.AudioFile(file) as source:
audio = r.record(source)
try:
result = r_type + ': ' + str(getattr(r, r_type)(audio))
except sr.UnknownValueError:
result = r_type + ': Speech Recognition could not understand audio'
except sr.RequestError as e:
result = r_type + ': Could not request results from Speech Recognition service; {0}'.format(e)
results.append(result)
return results
def main():
files = get_file_paths(DIRNAME) # get all file-paths of all files in dirname and subdirectories
for file in files: # execute for each file
(filepath, ext) = os.path.splitext(file) # get the file extension
file_name = os.path.basename(file) # get the basename for writing to output file
if ext == '.wav': # only interested if extension is '.wav'
a = recog_multiple(file) # result is returned to a
with open(OUTPUTFILE, 'a') as f: # write results to file
writer = csv.writer(f)
writer.writerow(['file_name','results'])
writer.writerow([file_name, a])
if __name__ == '__main__':
main()
bash: best practice to iterate over directory content until condition matches
Probably the safest way would be to iterate over the glob results directly, so you aren't vulnerable to the filenames containing special characters:
for path in "$1"/*; do
if file -b -- "$path" | grep -qi audio; then
printf 'Found an audio file %s\n' "$path"
process_audio_dir
exit
fi
done
# since we didn't exit above, most be no audio files
printf "Didn't find any audio files\n"
process_noaudio
Alternately, if you don't want to exit there, you could set a flag indicating that you found it and check that after the loop, and just use a break
inside the if
to exit the loop once you've found one.
The reason yours is applying grep
to the output of all the file
results, is that the glob expands first so you then run the command, for example
file -b dir/file1 dir/file2 dir/file3 ...
then the output of that command will be fed to grep
My solution puts the glob on the "outside" of the command, so we'll just run it on each file individually. Of course, there's more overhead with launching file
lots of times, so it's not obvious to me right away which is going to be more efficient. It'll probably depend on how many files there are, how far down the list the first audio file usually is and stuff like that.
As has been mentioned in the comments, it's dangerous to iterate over the printed filename results from find
or ls
, since those results would be subject to word splitting and potentially globbing depending on how exactly you do it. Using the for
loop above is the recommended way to do it generally. For more see Don't Parse ls
How to iterate files in directory with for loop in Bash
The for-loop is basically sound. However, if the directory is empty, the loop will be executed once, with the variable file
containing the literal text /var/spool/bandit24/*
.
The stat
message is not from the for
-loop, but from one of the commands in the loop.
The correct way would be to test if the directory is empty before you continue. You could put something like
if [ $(find . -type f | wc -l) -eq 0 ] ; then
echo "Nothing to do"
exit 0
fi
right after the cd
.
Some other comments on your script.
- If you do a
cd
in the script, you don't need to specify the full path anymore. - Your quoting is not really consistent. That may not be a problem if your file names never contain spaces or strange characters, but I would, for example
timeout -s 9 60 "./$file"
andrm -f "./file"
/var/spool/bandit/*
will never contain.
or..
, so that test is useless.- You could also replace the test with
if [ -f "$file" ] ; then
Related Topics
Checking If Object on Ftp Server Is File or Directory Using Python and Ftplib
How to Make Sessions Timeout in Flask
Convert a Python Dict to a String and Back
Format Strings VS Concatenation
Adding a Particle Effect to My Clicker Game
Is There a Multi-Dimensional Version of Arange/Linspace in Numpy
Bin Size in Matplotlib (Histogram)
Insert an Item into Sorted List in Python
Beautiful Soup 4 Find_All Don't Find Links That Beautiful Soup 3 Finds
How to Find Which Columns Contain Any Nan Value in Pandas Dataframe
Monkey Patching a Class in Another Module in Python
Difference Between Data and JSON Parameters in Python Requests Package
Lambda Function Don't Closure the Parameter in Python
How to Add a Custom Loglevel to Python's Logging Facility
Creating a Class Within a Function and Access a Function Defined in the Containing Function's Scope
What Do All the Distributions Available in Scipy.Stats Look Like
Timedelta to String Type in Pandas Dataframe
How to Get a List of All Indices of Repeated Elements in a Numpy Array