猛击黑客让我的脚沾满了蟒蛇。我几乎已经将bash脚本移植到了python中,但我似乎不知道如何将python vars传递给bash命令avconv,以便将.ogg音频文件转换为.mp3文件(sigh mp3 player不播放.ogg)。
无论如何,我想我会粘贴我的沙发,它是所有的工作,直到最后四行'如果'在最后'为'循环。当然,bash/avconv无法识别python“for”循环传递的python var“f”,也不知道如何继续这样做。
#!/usr/bin/python
#genre = GET SONG GENRE DIR
#if genre == rock+
# sGenreDir = /media/multiMediaA_intHdA720Gb/music/heavierAlt
import os
def get_filepaths(directory):
#This function will generate the file names in a directory tree by walking the tree either top-down or bottom-up. For each directory in the tree rooted at directory top (including top itself), it yields a 3 tuple (dirpath, dirnames, filenames).
file_paths = [] # create list to store full paths to each song contained recursively within
# walk the tree
for root, directories, files in os.walk(directory):
for filename in files:
# join the two strings in order to know the fill file path
filepath = os.path.join(root, filename)
file_paths.append(filepath) # add it to the list
return file_paths
# run the avove function and store its results in a variable
#full_file_paths = get_filepaths("/media/multiMediaA_intHdA720Gb/music/heavierAlt")
full_file_paths = get_filepaths("/media/multiMediaA_intHdA720Gb/music/rockAndHeavier")
#print len(full_file_paths)
cntr = 0
for f in full_file_paths:
if not (f.endswith(".mp3") or f.endswith(".ogg")):
del full_file_paths[cntr]
cntr = cntr + 1
#print len(full_file_paths)
# create random song list avoiding duplicate songs
destDir = "/home/keithpc/tmp/rsList" # will be selected by user
numSongs = 10 # number of songs will be chosen by the user
songList = [] # list to hold randomly selected songs
cntr = 1 # that will be incremented for each song appended to list 'songList'
while cntr <= numSongs: #begin random song selection/list creation
from random import choice
newSong = choice(full_file_paths)
if not newSong in songList: # 'if' newSong is not yet list element then add it and ++cntr
songList.append(newSong)
cntr = cntr + 1
print len(songList)
for f in songList:
print f
for f in songList:
if f.endswith(".mp3"): # cp .mp3 to player
import shutil
shutil.copy2(f, destDir)
else: # need to avconv .ogg before copying to player
import os
cmd = 'avconv -i f -c:a libmp3lame -q:a 4 -map_metadata 0:s $destDir/f/%ogg/mp3'
os.system(cmd)
更新:仅粘贴上述脚本的最后一部分,用于处理从src到dest的动态复制尝试avconv'ogg'到.mp3'的随机歌曲选择
# begin to compile random song list
#destDir = "/home/keithpc/tmp/rsList" # will be var supplied by user ; employed in 'for' loop below instead
numSongs = 3 # number of songs var will be supplied by user
songList = [] # list to hold randomly selected songs
cntr = 1 # that will be incremented for each song appended to list 'songList'
while cntr <= numSongs: # 'while' loop to iterate until 'numSongs' is matched by 'cntr'
from random import choice
newSong = choice(lFullFilePaths) # randomly selected song from list 'lFullFilePaths' to add to list 'songList' if it is not a duplicate
if not newSong in songList: # 'if' var does not exist in list 'songList' then add it and cntr++
songList.append(newSong)
cntr = cntr + 1
#print len(songList)
#for f in songList:
# print f
for f in songList:
destDir = "/home/keithpc/tmp/rsList" # will be var supplied by user ; needs to reset each iteration or else it concantanates with previous song details
if f.endswith(".mp3") # 'if' song type is '.mp3' then copy direct to mp3 player
import shutil
shutil.copy2(f, destDir)
else: # 'else' song type must be '.ogg' and so must be avcon'd to mp3 on the fly to mp3 player
import re # regex function to extract the song name from its path
sName = re.sub(r'^.*/', r'', f) # extract song name from it's path
#print sName
import subprocess
destDir = destDir + "/" + sName + "/%ogg/mp3" # create single var 'destDir' containing args bash/avconv should need to convert '.ogg' sending its output as '.mp3' to mp3 player
print(destDir)
subprocess.call(['avconv', '-i', '%s' % f, '-c:a', 'libmp3lame', '-q:a', '4', '-map_metadata', '0:s', '%s' % destDir])
当注释掉最终“subprocess”命令时,终端输出如下:
07:54 python $ ./ranS*.py
3
/media/multiMediaA_intHdA720Gb/music/rockAndHeavier/Radiohead/The_Best_Of/02_Paranoid_Android.ogg
/media/multiMediaA_intHdA720Gb/music/rockAndHeavier/Rod_Stewart/If_We_Fall_In_Love_Tonight/
15_All_For_Love__With_Bryan_Adams_And_Sting.ogg
/media/multiMediaA_intHdA720Gb/music/rockAndHeavier/Smashing_PumpkinsThe/Siamese_Dream/12_sweet_sweet.ogg
02_Paranoid_Android.ogg
/home/keithpc/tmp/rsList/02_Paranoid_Android.ogg/%ogg/mp3
15_All_For_Love__With_Bryan_Adams_And_Sting.ogg
/home/keithpc/tmp/rsList/15_All_For_Love__With_Bryan_Adams_And_Sting.ogg/%ogg/mp3
12_sweet_sweet.ogg
/home/keithpc/tmp/rsList/12_sweet_sweet.ogg/%ogg/mp3
看起来是对的。
未注释final'subprocess'的终端输出如下:
07:57 python $ ./ranS*.py
3
/media/multiMediaA_intHdA720Gb/music/rockAndHeavier/Guns_N_Roses/Patience_Live_At_The_Ritz_EP_Japanese/03_I_Used_To_Love_Her.ogg
/media/multiMediaA_intHdA720Gb/music/rockAndHeavier/SmithsThe/The_Best_Of_The_Smiths_Vol_1/05_girlfriend_in_a_coma_the_best_of_the_smiths_vol._1.mp3
/media/multiMediaA_intHdA720Gb/music/rockAndHeavier/Oasis/The_Masterplan/14_The_Masterplan.ogg
03_I_Used_To_Love_Her.ogg
/home/keithpc/tmp/rsList/03_I_Used_To_Love_Her.ogg/%ogg/mp3
avconv version 0.8.9-6:0.8.9-1, Copyright (c) 2000-2013 the Libav developers
built on Nov 3 2013 02:10:51 with gcc 4.7.2
Input #0, ogg, from '/media/multiMediaA_intHdA720Gb/music/rockAndHeavier/Guns_N_Roses/Patience_Live_At_The_Ritz_EP_Japanese/03_I_Used_To_Love_Her.ogg':
Duration: 00:02:48.69, start: 0.000000, bitrate: 186 kb/s
Stream #0.0: Audio: vorbis, 44100 Hz, stereo, s16, 192 kb/s
Metadata:
ARTIST : Guns N' Roses
ALBUM : Patience (Live At The Ritz) (EP - Japanese)
TITLE : I Used To Love Her
DATE : 1989
GENRE : Rock
track : 03
CDDB : 680adf09
Unable to find a suitable output format for '/home/keithpc/tmp/rsList/03_I_Used_To_Love_Her.ogg/%ogg/mp3'
14_The_Masterplan.ogg
/home/keithpc/tmp/rsList/14_The_Masterplan.ogg/%ogg/mp3
avconv version 0.8.9-6:0.8.9-1, Copyright (c) 2000-2013 the Libav developers
built on Nov 3 2013 02:10:51 with gcc 4.7.2
Input #0, ogg, from '/media/multiMediaA_intHdA720Gb/music/rockAndHeavier/Oasis/The_Masterplan/14_The_Masterplan.ogg':
Duration: 00:05:22.80, start: 0.000000, bitrate: 197 kb/s
Stream #0.0: Audio: vorbis, 44100 Hz, stereo, s16, 192 kb/s
Metadata:
ARTIST : Oasis
ALBUM : The Masterplan
TITLE : The Masterplan
DATE : 1998
GENRE : Rock
track : 14
CDDB : c00fd90e
Unable to find a suitable output format for '/home/keithpc/tmp/rsList/14_The_Masterplan.ogg/%ogg/mp3'
也许问题是/%ogg/mp3试图将“.ogg”ext替换为“.mp3”ext,作为avconv进程的一部分?它看起来很近,如果有人可以有任何糖帮助我回家免费。
顺便说一句,我一直在仔细检查iNet,特别是StackOverflow,以获得适用的帮助。所以在请求帮助之前我有无线电调频。我只是不能让这最后一部分与bash shell交互。
谢谢,
打盹
最佳答案
不久前,我创建了一个类似的脚本,将大量视频转换成一种可以在我的游戏机上播放的格式。以下是我将在您当前代码中更改的内容:
正如martijn pieters建议的那样,我不会使用os.system来调用avconv,而是尝试以下操作:
for f in songList:
if f.endswith(".mp3"): # cp .mp3 to player
import shutil
shutil.copy2(f, destDir)
else: # need to avconv .ogg before copying to player
import subprocess
subprocess.call(['avconv', '-i', '%s' % f, '-c:a',
'libmp3lame', '-q:a', '4', '-map_metadata',
'0:s', '$destDir/f/%ogg/mp3'])
以下是对更改的简要描述。首先,代码现在使用的是导入的
os.system
,而不是subprocess.call
。第二步,我将传递给os
的命令重新格式化为使用avconv
而不是直接的'%s' % f
,这将告诉python“嘿,使用f
中存储的内容来填充此空白!”,而原始代码是“python,在这里使用f!”。重新格式化传递的命令时,您将注意到每个段都包含在引号中,这是由于子流程如何解释传递给它的参数。我确信其他人能比我更好地解释原因和方法,但是简单地说,在每个论点之间会自动添加一个空格。--编辑--
好的,在检查了更新后的信息之后,我回去修改了提供的代码。我无法完全测试,因为我不在家,目前没有avconv或安装在这台计算机上的能力。不过,我确实用打印语句替换了
f
和shutil
行,一切都“看起来”正常。这是代码,下面将对更改进行简要说明。
#!/usr/bin/python
import os
import subprocess
import shutil
from random import choice
def get_filepaths(directory):
filenames = {}
for root, directories, files in os.walk(directory):
for file in files:
filenames[file] = os.path.join(root, file)
return filenames
def remove_file(d, key):
r = dict(d)
del r[key]
return r
full_file_paths = get_filepaths("/media/multiMediaA_intHdA720Gb/music/rockAndHeavier")
to_remove = []
for file, file_path in full_file_paths.items():
if not (file.endswith('.mp3') or file.endswith('.ogg')):
to_remove.append(file)
for item in to_remove:
full_file_paths = remove_file(full_file_paths, item)
destDir = "/home/keithpc/tmp/rsList"
songList = []
numSongs = 10
cntr = 1
while cntr <= numSongs:
newSong = choice(full_file_paths.keys())
if newSong not in songList:
songList.append(newSong)
cntr += 1
for f in songList:
finalDest = destDir + '/%ogg/mp3'
if f.endswith('.mp3'):
shutil.copy2(full_file_paths.get(f), '%s/%s' %(destDir, f))
else:
subprocess.call(['avconv', '-i', '%s' % full_file_paths.get(f), '-c:a',
'libmp3lame', '-q:a', '4', '-map_metadata', '0:s',
'%s/%s.mp3' % (finalDest, f.strip('ogg'))])
第一个更改是在
subprocess.call
定义中,我觉得最后重命名会简单一些。而不是像以前那样构建一个列表,而是使用文件的实际文件名作为键,值是文件的整个路径来创建字典。下一个是
to_remove = []
def remove_file(d, key):
r = dict(d)
del r[key]
return r
for file, file_path in full_file_paths.items():
if not (file.endswith('.mp3') or file.endswith('.ogg')):
to_remove.append(file)
for item in to_remove:
full_file_paths = remove_file(full_file_paths, item)
这类似于你最初删除不需要的文件,但重写来处理字典的方式。
最后一个变化是最后一个
get_filepaths
循环。这种调整主要是因为我忘记了avconv(正式称为ffmpeg)的一个重要特性,即avconv要求我们告诉它目标文件名是什么。如果我没记错,shuil还需要知道目标文件名,至少它在windows上不能正常工作。for f in songList:
finalDest = destDir + '/%ogg/mp3'
if f.endswith('.mp3'):
shutil.copy2(full_file_paths.get(f), '%s/%s' %(destDir, f))
else:
subprocess.call(['avconv', '-i', '%s' % full_file_paths.get(f), '-c:a',
'libmp3lame', '-q:a', '4', '-map_metadata', '0:s',
'%s/%s.mp3' % (finalDest, f.strip('.ogg'))])
希望这有帮助。
关于python - 需要将python vars传递给bash avconv命令,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20839980/