Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于拆分和连接mp3文件的Python库_Python_Mp3 - Fatal编程技术网

用于拆分和连接mp3文件的Python库

用于拆分和连接mp3文件的Python库,python,mp3,Python,Mp3,有很多lib可以用来处理mp3标签,但我只需要两个函数——将mp3文件分成两部分,第二个用于合并5个mp3文件 你有什么建议吗? 谢谢 看看维基百科上的。在python中使用二进制读取模式编辑MP3文件s=open(文件名为'rb')。read()将把整个文件放入表示文件中原始字节的字符串对象中(例如\xeb\xfe\x80)。然后,您可以搜索和编辑字符串,并使用括号用索引寻址字节偏移量:s[n]。最后,只需对新文件中所需的MP3帧进行二进制写入,将ID3头附加到要组成每个文件的帧集。签出及其P

有很多lib可以用来处理mp3标签,但我只需要两个函数——将mp3文件分成两部分,第二个用于合并5个mp3文件

你有什么建议吗?
谢谢

看看维基百科上的。在python中使用二进制读取模式编辑MP3文件
s=open(文件名为'rb')。read()
将把整个文件放入表示文件中原始字节的字符串对象中(例如
\xeb\xfe\x80
)。然后,您可以搜索和编辑字符串,并使用括号用索引寻址字节偏移量:
s[n]
。最后,只需对新文件中所需的MP3帧进行二进制写入,将ID3头附加到要组成每个文件的帧集。

签出及其Python包装器。

使用unix split命令:

split -b 200k file.mp3 output_
cat output_2.mp3 output_3.mp3 output_4.mp3 > output.mp3
这将输出输出a,输出b,输出c

然后,您只需重命名即可获得mp3文件

for file in ./output_*; do mv "$file" "$(basename $file).mp3"; done
这将输出a.mp3、b.mp3、c.mp3。。。所有这些文件(除最后一个文件外,可能是)的大小都是200kb,并且输出_x的总大小与file.mp3相同

您可以使用
du
(磁盘使用)命令获取文件的字节数,然后决定要剪切多少字节

du -sh file.mp3
然后,要加入,请使用cat命令:

split -b 200k file.mp3 output_
cat output_2.mp3 output_3.mp3 output_4.mp3 > output.mp3
当然,您可以将所有这些都放在一个shell脚本中,并从python中调用它。

我编写了一个库(),基本上就是为了这个用例:

from pydub import AudioSegment

sound = AudioSegment.from_mp3("/path/to/file.mp3")

# len() and slicing are in milliseconds
halfway_point = len(sound) / 2
second_half = sound[halfway_point:]

# Concatenation is just adding
second_half_3_times = second_half + second_half + second_half

# writing mp3 files is a one liner
second_half_3_times.export("/path/to/new/file.mp3", format="mp3")
增加沉默的差距 如果要在声音的各个部分之间添加静音:

two_sec_silence = AudioSegment.silent(duration=2000)
sound_with_gap = sound[:1000] + two_sec_silence + sound[1000:]

下面是我在不重新编码的情况下使用python拆分MP3的尝试。并非所有种类的MP3文件都受支持,我很乐意接受建议或改进。脚本被硬编码为55秒分割,但代码演示了一般原则

from __future__ import print_function
import struct
import sys

#MP3 frames are not independent because of the byte reservoir. This script does not account for
#that in determining where to do the split.

def SplitMp3(fi, splitSec, out):

    #Constants for MP3
    bitrates = {0x0: "free", 0x1: 32, 0x2: 40, 0x3: 48, 0x4: 56, 0x5: 64, 0x6: 80, 0x7: 96, 0x8: 112,
        0x9: 128, 0xa: 160, 0xb: 192, 0xc: 224, 0xd: 256, 0xe: 320, 0xf: "bad"}
    freqrates = {0x0: 44100, 0x1: 48000, 0x2: 32000, 0x3: "reserved"}
    countMpegFrames = 0
    frameDuration = 0.026
    unrecognizedBytes = 0
    splitFrame = int(round(splitSec / frameDuration))

    while True:

        startPos = fi.tell()

        #Check for 3 byte headers
        id3Start = fi.read(3)
        if len(id3Start) == 3:

            if id3Start == b'TAG':
                print ("Found ID3 v1/1.1 header")
                fi.seek(startPos + 256)
                continue

            if id3Start == b'ID3':
                #Possibly a ID3v2 header
                majorVer, minorVer, flags, encSize = struct.unpack(">BBBI", fi.read(7))
                if majorVer != 0xFF and minorVer != 0xFF:
                    encSize1 = (encSize & 0x7f000000) >> 24
                    encSize2 = (encSize & 0x7f0000) >> 16
                    encSize3 = (encSize & 0x7f00) >> 8
                    encSize4 = (encSize & 0x7f)
                    if encSize1 < 0x80 and encSize2 < 0x80 and encSize3 < 0x80 and encSize4 < 0x80:
                        size = ((encSize & 0x7f000000) >> 3) + ((encSize & 0x7f0000) >> 2) + ((encSize & 0x7f00) >> 1) + (encSize & 0x7f)
                        unsync = (flags >> 7) & 0x1
                        extendedHeader = (flags >> 6) & 0x1
                        experimental = (flags >> 5) & 0x1
                        print ("Found ID3v2 header")
                        print ("version", majorVer, minorVer, unsync, extendedHeader, experimental)
                        print ("size", size)
                        #TODO extendedHeader not supported yet

                        fi.seek(startPos + 10 + size)
                        continue

        #Check for 4 byte headers
        fi.seek(startPos)
        headerRaw = fi.read(4)
        if len(headerRaw) == 4:
            headerWord = struct.unpack(">I", headerRaw)[0]

            #Check for MPEG-1 audio frame
            if headerWord & 0xfff00000 == 0xfff00000:
                print ("Possible MPEG-1 audio header", hex(headerWord))
                countMpegFrames += 1
                ver = (headerWord & 0xf0000) >> 16
                bitrateEnc = (headerWord & 0xf000) >> 12
                freqEnc = (headerWord & 0xf00) >> 8
                mode = (headerWord & 0xf0) >> 4
                cpy = (headerWord & 0xf)
                if ver & 0xe == 0xa and freqEnc != 0xf:
                    print ("Probably an MP3 frame")
                    bitrate = bitrates[bitrateEnc]
                    freq = freqrates[freqEnc >> 2]
                    padding = ((freqEnc >> 1) & 0x1) == 1
                    print ("bitrate", bitrate, "kbps")
                    print ("freq", freq, "Hz")
                    print ("padding", padding)
                    frameLen = int((144 * bitrate * 1000 / freq ) + padding)

                    #Copy frame to output
                    fi.seek(startPos)
                    frameData = fi.read(frameLen)
                    if countMpegFrames >= splitFrame:
                        out.write(frameData)

                    fi.seek(startPos + frameLen)
                    continue
                else:
                    raise RuntimeError("Unsupported format:", hex(ver), "header:", hex(headerWord))

        #If no header can be detected, move on to the next byte
        fi.seek(startPos)
        nextByteRaw = fi.read(1)
        if len(nextByteRaw) == 0:
            break #End of file
        unrecognizedBytes += 1

    print ("unrecognizedBytes", unrecognizedBytes)
    print ("countMpegFrames", countMpegFrames)
    print ("duration", countMpegFrames * frameDuration, "sec")

if __name__=="__main__":
    fi = open(sys.argv[1], "rb")
    out = open("test.mp3", "wb")
    SplitMp3(fi, 55.0, out)
    out.close()
from\uuuuu future\uuuuu导入打印功能
导入结构
导入系统
#MP3帧不是独立的,因为字节库。此脚本不考虑
#这是决定在哪里进行拆分的关键。
def SplitMp3(fi、splitSec、out):
#MP3的常数
比特率={0x0:“空闲”,0x1:32,0x2:40,0x3:48,0x4:56,0x5:64,0x6:80,0x7:96,0x8:112,
0x9:128、0xa:160、0xb:192、0xc:224、0xd:256、0xe:320、0xf:“坏”}
频率={0x0:44100,0x1:48000,0x2:32000,0x3:“保留”}
countMpegFrames=0
帧持续时间=0.026
无法识别的字节=0
splitFrame=int(四舍五入(splitSec/frameDuration))
尽管如此:
startPos=fi.tell()
#检查3字节头
id3Start=fi.read(3)
如果len(id3Start)==3:
如果id3Start==b'TAG':
打印(“找到ID3 v1/1.1标题”)
fi.seek(startPos+256)
持续
如果id3Start==b'ID3':
#可能是ID3v2头
主服务器,最小服务器,标志,encSize=struct.unpack(“>BBBI”,fi.read(7))
如果是majorVer!=0xFF和minorVer!=0xFF:
encSize1=(encSize&0x7f000000)>>24
encSize2=(encSize&0x7f0000)>>16
encSize3=(encSize&0x7f00)>>8
encSize4=(encSize&0x7f)
如果encSize1<0x80,encSize2<0x80,encSize3<0x80,encSize4<0x80:
大小=((encSize&0x7f000000)>>3)+((encSize&0x7f0000)>>2)+((encSize&0x7f00)>>1)+(encSize&0x7f)
不同步=(标志>>7)和0x1
extendedHeader=(标志>>6)和0x1
实验=(标志>>5)和0x1
打印(“找到ID3v2标题”)
打印(“版本”、主服务器、minorVer、不同步、extendedHeader、实验性)
打印(“大小”,大小)
#尚未支持TODO extendedHeader
fi.seek(startPos+10+尺寸)
持续
#检查4字节头
fi.seek(startPos)
headerRaw=fi.read(4)
如果len(headerRaw)==4:
headerWord=struct.unpack(“>I”,headerRaw)[0]
#检查MPEG-1音频帧
如果headerWord&0xfff00000==0xfff00000:
打印(“可能的MPEG-1音频头”,十六进制(头字))
countMpegFrames+=1
版本=(headerWord&0xf0000)>>16
比特率编码=(headerWord&0xf000)>>12
频率=(headerWord&0xf00)>>8
模式=(headerWord&0xf0)>>4
cpy=(headerWord&0xf)
如果版本&0xe==0xa且频率!=0xf:
打印(“可能是MP3帧”)
比特率=比特率[bitrateEnc]
freq=freqrates[frequenc>>2]
填充=((频率>>1)和0x1)==1
打印(“比特率”,比特率,“kbps”)
打印(“频率”,频率,赫兹”)
打印(“填充”,填充)
frameLen=int((144*比特率*1000/频率)+填充)
#将帧复制到输出
fi.seek(startPos)
frameData=fi.read(frameLen)
如果countMpegFrames>=拆分帧:
out.write(帧数据)
fi.seek(startPos+frameLen)
持续
其他:
raise RUNTIMERROR(“不支持的格式:”,十六进制(版本),“页眉:”,十六进制(页眉))
#如果未检测到任何标头,请转到下一个字节
fi.seek(startPos)
nextByteRaw=fi.read(1)
如果len(nextByteRaw)==0:
断开#文件结尾
无法识别的字节数+=1
打印(“未识别字节”,未识别字节)
打印(“countMpegFrames”,countMpegFrames)
打印(“持续时间”,countMpegFrames*frameDuration,秒”)
如果名称=“\uuuuu main\uuuuuuuu”:
fi=打开(系统参数[1],“rb”)
out=打开(“test.mp3”、“wb”)
斯普利姆普