2つ以上の.wavファイルを1つにマージしてから.mp3に変換したいのですが、これをSwiftで実行したいと思います(または少なくともSwiftプロジェクトに含めるオプションがあります) 。
Swiftの2つの.wavファイルをマージすることは問題ありません。 これが私の例です Swiftプロジェクトにlameライブラリを追加する方法とその使用方法(Swiftで使用するようにObjective C lameコードの使用構文を変更する方法)がわかりません。 。
Swiftで立ち往生したので、Objective CでLameライブラリを試しました。cafを.mp3に変換するためのサンプルコードを見つけたので、試しました。これが私が試したことです:
- (void) toMp3
{
NSString *cafFilePath = [[NSBundle mainBundle] pathForResource:@"sound" ofType:@"caf"];
NSString *mp3FileName = @"Mp3File";
mp3FileName = [mp3FileName stringByAppendingString:@".mp3"];
NSString *mp3FilePath = [[NSHomeDirectory() stringByAppendingFormat:@"/Documents/"] stringByAppendingPathComponent:mp3FileName];
NSLog(@"%@", mp3FilePath);
@try {
int read, write;
FILE *pcm = fopen([cafFilePath cStringUsingEncoding:1], "rb"); //source
fseek(pcm, 4*1024, SEEK_CUR); //skip file header
FILE *mp3 = fopen([mp3FilePath cStringUsingEncoding:1], "wb"); //output
const int PCM_SIZE = 8192;
const int MP3_SIZE = 8192;
short int pcm_buffer[PCM_SIZE*2];
unsigned char mp3_buffer[MP3_SIZE];
lame_t lame = lame_init();
lame_set_in_samplerate(lame, 44100);
lame_set_VBR(lame, vbr_default);
lame_init_params(lame);
do {
read = fread(pcm_buffer, 2*sizeof(short int), PCM_SIZE, pcm);
if (read == 0)
write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
else
write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);
fwrite(mp3_buffer, write, 1, mp3);
} while (read != 0);
lame_close(lame);
fclose(mp3);
fclose(pcm);
}
@catch (NSException *exception) {
NSLog(@"%@",[exception description]);
}
@finally {
[self performSelectorOnMainThread:@selector(convertMp3Finish)
withObject:nil
waitUntilDone:YES];
}
}
- (void) convertMp3Finish
{
}
しかし、この結果は、ノイズのある.mp3だけです。
したがって、3つの問題を修正する必要があります。
IOSでのmp3のエンコードと変換について多くの質問があることは知っていますが、Swiftの例では質問が見つからず、Objective Cコード(上記のコードのみ)での例も見つかりません。手伝ってくれてありがとう
私は非常に多くの親指を立て、nareshからの回答はあまり役に立たないので、私の実用的な解決策を投稿したいと思います。
そして今、ソースコード。だから最初のラッパー。 .wavファイルを.mp3に変換するためのクラスです。多くの変更(おそらく出力ファイルのパラメーターやその他のオプション)がある可能性がありますが、誰もがそれを変更できると思います。これはSwiftに書き換えることができると思いますが、その方法がわかりませんでした。したがって、ObjectiveCクラスです。
#import "AudioWrapper.h"
#import "lame/lame.h"
@implementation AudioWrapper
+ (void)convertFromWavToMp3:(NSString *)filePath {
NSString *mp3FileName = @"Mp3File";
mp3FileName = [mp3FileName stringByAppendingString:@".mp3"];
NSString *mp3FilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:mp3FileName];
NSLog(@"%@", mp3FilePath);
@try {
int read, write;
FILE *pcm = fopen([filePath cStringUsingEncoding:1], "rb"); //source
fseek(pcm, 4*1024, SEEK_CUR); //skip file header
FILE *mp3 = fopen([mp3FilePath cStringUsingEncoding:1], "wb"); //output
const int PCM_SIZE = 8192;
const int MP3_SIZE = 8192;
short int pcm_buffer[PCM_SIZE*2];
unsigned char mp3_buffer[MP3_SIZE];
lame_t lame = lame_init();
lame_set_in_samplerate(lame, 44100);
lame_set_VBR(lame, vbr_default);
lame_init_params(lame);
do {
read = fread(pcm_buffer, 2*sizeof(short int), PCM_SIZE, pcm);
if (read == 0)
write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
else
write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);
fwrite(mp3_buffer, write, 1, mp3);
} while (read != 0);
lame_close(lame);
fclose(mp3);
fclose(pcm);
}
@catch (NSException *exception) {
NSLog(@"%@",[exception description]);
}
@finally {
[self performSelectorOnMainThread:@selector(convertMp3Finish)
withObject:nil
waitUntilDone:YES];
}
}
オーディオファイルを連結し、.wavファイルを.mp3に変換するためのメソッドを呼び出すためのSwift AudioHelperクラス:
import UIKit
import AVFoundation
protocol AudioHelperDelegate {
func assetExportSessionDidFinishExport(session: AVAssetExportSession, outputUrl: NSURL)
}
class AudioHelper: NSObject {
var delegate: AudioHelperDelegate?
func concatenate(audioUrls: [NSURL]) {
//Create AVMutableComposition Object.This object will hold our multiple AVMutableCompositionTrack.
var composition = AVMutableComposition()
var compositionAudioTrack:AVMutableCompositionTrack = composition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID())
//create new file to receive data
var documentDirectoryURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first! as! NSURL
var fileDestinationUrl = NSURL(fileURLWithPath: NSTemporaryDirectory().stringByAppendingPathComponent("resultmerge.wav"))
println(fileDestinationUrl)
StorageManager.sharedInstance.deleteFileAtPath(NSTemporaryDirectory().stringByAppendingPathComponent("resultmerge.wav"))
var avAssets: [AVURLAsset] = []
var assetTracks: [AVAssetTrack] = []
var durations: [CMTime] = []
var timeRanges: [CMTimeRange] = []
var insertTime = kCMTimeZero
for audioUrl in audioUrls {
let avAsset = AVURLAsset(URL: audioUrl, options: nil)
avAssets.append(avAsset)
let assetTrack = avAsset.tracksWithMediaType(AVMediaTypeAudio)[0] as! AVAssetTrack
assetTracks.append(assetTrack)
let duration = assetTrack.timeRange.duration
durations.append(duration)
let timeRange = CMTimeRangeMake(kCMTimeZero, duration)
timeRanges.append(timeRange)
compositionAudioTrack.insertTimeRange(timeRange, ofTrack: assetTrack, atTime: insertTime, error: nil)
insertTime = CMTimeAdd(insertTime, duration)
}
//AVAssetExportPresetPassthrough => concatenation
var assetExport = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetPassthrough)
assetExport.outputFileType = AVFileTypeWAVE
assetExport.outputURL = fileDestinationUrl
assetExport.exportAsynchronouslyWithCompletionHandler({
self.delegate?.assetExportSessionDidFinishExport(assetExport, outputUrl: fileDestinationUrl!)
})
}
func exportTempWavAsMp3() {
let wavFilePath = NSTemporaryDirectory().stringByAppendingPathComponent("resultmerge.wav")
AudioWrapper.convertFromWavToMp3(wavFilePath)
}
}
ブリッジヘッダーには次のものが含まれます。
#import "lame/lame.h"
#import "AudioWrapper.h"
AVAssetReader
およびAVAssetWriter
であるファイルとの間でメディアを読み書きするための専用クラスがあり、AVAssetExportSession
を使用してmp3ファイルとしてエクスポートできます。または、使用できます https://github.com/michaeltyson/TPAACAudioConverter