Pydub audio export has silence at the start? - python-3.x

I wrote a python script to take audio in 30 minute mp3's and slice it into unix timestamped, second long files. The source audio files are 192kbps, 441000Hz, stero mp3 files.
I want it that way for a service that archives audio from a radio station (where I work) and can deliver it to a user over a given start and end time, to the second. We had the server shut down for an hour for maintenance (we try not to but it happens) and we recorded it over that time using a different computer that saved our audio in 30-minute chunks. Normally this archive server saves the second-long chunks itself without issue.
The function that does the conversion, given a 30 minute input audio file, the directory to save the output chunks in, and the start time of the file as a unix timestamp:
def slice_file( infile, workingdir, start ):
#find the duration of the input clip in millliseconds
duration_in_milliseconds = len(infile)
print ("Converting " + working_file + " (", end="", flush=True)
song = infile
#grab each one second slice and save it from the first second to the last whole second in the file
for i in range(0,duration_in_milliseconds,1*one_second):
#get the folder where this second goes:
arr = datefolderfromtimestamp( int(start) + (int(i/1000)))
#print ("Second number: %s \n" % (int(i/1000)) )
offset = (i + one_second)
current_second = song[i:offset]
ensure_dir(working_directory + "/" + arr[0] + "/" + arr[1] + "/" + arr[2] + "/")
filename = os.path.normpath(working_directory + "/" + arr[0] + "/" + arr[1] + "/" + arr[2] + "/" + str(int(start) + (int(i/1000))) + "-second.mp3")
current_second.export(filename, format="mp3")
#indicate some sort of progress is happening by printing a dot every three minutes processed
if( i % (3*60*one_second) == 0 ):
print ('.', end="", flush=True)
print (")")
My issue is that all the second files converted by this script seem to be longer than a second with on average 70 ms of silence at the start of them. When I download files from my archiver server it gives me all the files concatenated together, so it sounds terrible and glitchy.
Can someone help me out? I'm not sure where this error is coming from.
My full script if you're curious:
http://pastebin.com/fy8EkVSz

Update: Found out the source of this - LAME adds buffers to the start of the file.
See: http://lame.sourceforge.net/tech-FAQ.txt

Related

How to write binary stream as an opus file - python

I'm trying to write an opus file out of a binary stream using the code below, but the resulting files are unplayable. It seems that dumping it into the container won't work. Any ideas as to how to go about writing these audio files?
audio_start.append(start_audio + name[2])
audio_end.append(start_audio + name[2] + name[3])
count = 0
for i, j in zip(audio_start, audio_end):
in_file.seek(0)
count += 1
audio_output_path = input[:-4] + "audio_" + str(count) + ".opus"
with open(audio_output_path, 'wb') as out_audio:
out_audio.write(in_file.read()[i:j])
out_audio.close()

Renaming files with python results in duplicate files

I have a folder with the following files:
[11111]Text.txt
[22222]Text.txt
[33333]Text.txt
[44444]Text.txt
I need rename the files to remove the [11111] designation from the beginning of the file name, however that results in duplicate file names.
I wrote a basic script out that will strip the [11111] from the first file, and if any duplication occurs with subsequent files it will name the file [Duplicate]_[#]_text.txt where [#] is a random number
When I ran the code, it renamed the first file correctly, and renamed the second file with the required string, but it did not continue with the other files, and instead presented the following error:
FileExistsError: [WinError 183] Cannot create a file when that file already exists: 'Destination/[33333]Text.txt' -> 'Destination/[Duplicate]_[1]Text.txt'
The code below is what I have currently, though i have tried several iterations also
Location = (Destination_Folder)
Dupe_Counter = random.randint(0,255)
for filename in os.listdir(Location):
try:
if filename.startswith("["):
os.rename(Location + filename, Location + filename[7:])
except:
os.rename(Location + filename, Location +'[Duplicate]_' + '[' + str(Dupe_Counter) +']' + filename[7:])
I'm assuming that it's not actually picking up the Dupe_Counter when creating new files, however I'm not 100% sure where i'm going wrong.
Any help appreciated.
In your Dupe_Counter you are generating a random number that can collide with the results sometimes. But on top of that, you are generating the random Dupe_Counter once only.
Try to generate a random number for each iteration.
Location = (Destination_Folder)
for filename in os.listdir(Location):
Dupe_Counter = random.randint(0,255)
try:
if filename.startswith("["):
os.rename(Location + filename, Location + filename[7:])
except:
os.rename(Location + filename, Location +'[Duplicate]_' + '[' + str(Dupe_Counter) +']' + filename[7:])
But I would recommend generating an increasing sequence for renaming the files and better understanding.
Something Like this:
Location = (Destination_Folder)
for filename in os.listdir(Location):
Dupe_Counter = 101
try:
if filename.startswith("["):
os.rename(Location + filename, Location + filename[7:])
except:
os.rename(Location + filename, Location +'[Duplicate]_' + '[' + str(Dupe_Counter) +']' + filename[7:])
Dupe_Counter += 1
Hope I've been of some help.

Python3 _io.TextIOWrapper error when opening a file with notepad

I am stuck from a couple of days on an issue in my micro Address Book project. I have a function that writes all records from a SQLite3 Db on file in order to open in via OS module, but as soon as I try to open the file, Python gives me the following error:
Error while opening tempfile. Error:startfile: filepath should be string, bytes or os.PathLike, not _io.TextIOWrapper
This is the code that I have to write records on file and to open it:
source_file_name = open("C:\\workdir\\temp.txt","w")
#Fetching results from database and storing in result variable
self.cur.execute("SELECT id, first_name, last_name, address1, address2, zipcode, city, country, nation, phone1, phone2, email FROM contacts")
result = self.cur.fetchall()
#Writing results into tempfile
source_file_name.write("Stampa Elenco Contatti\n")
for element in result:
source_file_name.write(str(element[0]) + "|" + str(element[1]) + "|" + str(element[2]) + "|" + str(element[3]) + "|" + str(element[4]) + "|" + str(element[5]) + "|" + \
str(element[6]) + "|" + str(element[7]) + "|" + str(element[8]) + "|" + str(element[9]) + "|" + str(element[10]) + "|" + str(element[11]) + "\n")
#TODO: Before exiting printing function you MUST:
# 1. filename.close()
# 2. exit to main() function
source_file_name.close()
try:
os.startfile(source_file_name,"open")
except Exception as generic_error:
print("Error while opening tempfile. Error:" + str(generic_error))
finally:
main()
Frankly I don't understand what this error means, in my previous code snippets I've always handled text files without issues, but I realize this time it's different because I am picking my stream from a database. Any ideas how to fix it?
Thanks in advance, and sorry for my english...
Your problem ultimately stems from poor variable naming. Here
source_file_name = open("C:\\workdir\\temp.txt","w")
source_file_name does not contain the source file name. It contains the source file itself (i.e., a file handle). You can't give that to os.startfile(), which expects a file path (as the error also says).
What you meant to do is
source_file_name = "C:\\workdir\\temp.txt"
source_file = open(source_file_name,"w")
But in fact, it's much better to use a with block in Python, as this will handle closing the file for you.
It's also better to use a CSV writer instead of creating the CSV manually, and it's highly advisable to set the file encoding explicitly.
import csv
# ...
source_file_name = "C:\\workdir\\temp.txt"
with open(source_file_name, "w", encoding="utf8", newline="") as source_file:
writer = csv.writer(source_file, delimiter='|')
source_file.write("Stampa Elenco Contatti\n")
for record in self.cur.fetchall():
writer.writerow(record)
# alternative to the above for loop on one line
# writer.writerows(self.cur.fetchall())

files are saved repeatedly with single name, no looping, no ranging

My codes runs well, but have one flaw. They are not saving accordingly. For example, Let's say I caught 3 jpeg files, when I ran the codes, it saves 3 times on slot 1, 3 times on slot 2, and 3 times on slot 3. So I ended up with 3 same files.
I think there is something wrong with my looping logic?
If I changed for n in range(len(soup_imgs)): to for n in range(len(src)):, the operation saves infinitely of the last jpeg files.
soup_imgs = soup.find(name='div', attrs={'class':'t_msgfont'}).find_all('img', alt="", src=re.compile(".jpg"))
for i in soup_imgs:
src = i['src']
print(src)
dirPath = "C:\\__SPublication__\\"
img_folder = dirPath + '/' + soup_title + '/'
if (os.path.exists(img_folder)):
pass
else:
os.mkdir(img_folder)
for n in range(len(src)):
n += 1
img_name = dirPath + '/' + soup_title + '/' + str({}).format(n) + '.jpg'
img_files = open(img_name, 'wb')
img_files.write(requests.get(src).content)
print("Outputs:" + img_name)
I am amateur in coding, just started not long ago as a hobby of mine. Please give me some guidance, chiefs.
Try this when you are writing your image files:
from os import path
for i, img in enumerate(soup_imgs):
src = img['src']
img_name = path.join(dirPath, soup_title, "{}.jpg".format(i))
with open(img_name, 'wb') as f:
f.write(requests.get(src).content)
print("Outputs:{}".format(img_name))
You need to loop over all image sources, rather than using the last src value from a previous for block.
I've also added a safer method for joining directory and file paths that should be OS independent. Finally, when opening a file, always use the with open() as f: construct - this way Python will automatically close the filehandle for you.

Renaming, Moving, and Deleting Original Directory

I'm trying to right a script that will walk through a given directory and rename, move, and delete the original directory. Each directory has a *.mp4 file and a subfolder containing *.jpg files. I'm having trouble deleting the original directory when I'm done renaming and moving the files. What so far is:
import datetime, os, re, shutil, logging, smtplib
logging.basicConfig(level = logging.INFO, format = ' %(asctime)s - %(levelname)s - %(message)s')
#logging.disable(logging.info)
path = '\\\\RT-N66U\\sda2\\Documents'
desired_text1 = re.compile(r'^\d{3}_[a-zA-Z]+\d{3}.jpg')
desired_text2 = re.compile(r'^\d{3}_[a-zA-Z]+_\d{3}.jpg')
renamed_files = ''
for folderName, subfolders, filenames in os.walk(path):
if folderName.startswith(path + '\\GEO-'):
logging.info('The current folder is ' + folderName)
for subfolder in subfolders:
if subfolder.startswith('Pics'):
pic_folder = subfolder
for filename in filenames:
if filename.endswith('.mp4'):
changed_date = datetime.datetime.strptime(filename[3:17], '%b %d, %Y').strftime('%y.%m.%d') # Changes the name of the date to the desired format
year = datetime.datetime.strptime(filename[3:17], '%b %d, %Y').strftime('%Y')
name = filename[20:-25]
name = name.lower()
modified_name = '.'.join(re.findall('\S+', name))
final_name = 'geo.' + changed_date + '.' + modified_name
if not os.path.exists('\\\\RT-N66U\\sda2\\Me\\GEO\\%s\\%s\\%s' % (year, changed_date[3:5], final_name)):
os.makedirs('\\\\RT-N66U\\sda2\\Me\\GEO\\%s\\%s\\%s' % (year, changed_date[3:5], final_name))
if not os.path.exists('\\\\RT-N66U\\sda2\\Me\\GEO\\%s\\%s\\%s\\%s' % (year, changed_date[3:5], final_name, pic_folder)):
os.makedirs('\\\\RT-N66U\\sda2\\Me\\GEO\\%s\\%s\\%s\\%s' % (year, changed_date[3:5], final_name, pic_folder))
if filename.endswith('.mp4'):
logging.info(filename)
os.rename(folderName + '\\' + filename, '\\\\RT-N66U\\sda2\\Me\\GEO\\%s\\%s\\%s\\%s.mp4' % (year, changed_date[3:5], final_name, final_name))
# This part will logg and rename the files by adding a '_'
mo1 = desired_text1.search(filename)
mo2 = desired_text2.search(filename)
if mo1:
logging.info(folderName + '\\' + filename)
os.rename(folderName + '\\' + filename, '\\\\RT-N66U\\sda2\\Me\\GEO\\%s\\%s\\%s\\%s\\%s_%s' % (year, changed_date[3:5], final_name, pic_folder, filename[:-7], filename[-7:]))
renamed_files += filename + ' -> ' + filename[:-7] + '_' + filename[-7:] + '\n'
elif mo2:
logging.info(folderName + '\\' + filename)
os.rename(folderName + '\\' + filename, '\\\\RT-N66U\\sda2\\Me\\GEO\\%s\\%s\\%s\\%s\\%s' % (year, changed_date[3:5], final_name, pic_folder, filename))
renamed_files += filename + '\n'
# This part will check if the directory is empty and delete it if so
if os.listdir(folderName) == []:
logging.info(folderName)
shutil.rmtree(folderName)
What ends up happening is that all sub-directories will be deleted if they're empty and leaving the primary directory empty. I would like the primary directory to be removed as well, since all the files have been moved. Is there a way to accomplish this within the for statement?
If you mean deleting the directory known as folderName inside your main for loop, I think it's not really possible since you're iterating over an object that contains it. Like if inside a for i in this_list: you would like to remove an object from this_list. This is not possible before you're out of the loop.
In order to achieve what you want, I would write a function to recurse into the folder tree. The idea would be something like:
def process_folder(folder_name):
do some stuff on files
get the subfolders of folder_name
for f in subfolders:
process_folder(subfolder_name)
if subfolder_name is empty, delete it
maybe do some other stuff on files
and in the main script, call process_folder(path). (This would leave only the top folder there even if it's empty though, so be sure you don't want to delete it; or to call process_folder at a higher level, or to add an instruction to delete it too if it's empty).

Resources