ios swift audio mp3 lame

Swift de iOS: fusiona y convierte archivos.wav a.mp3



audio lame (2)

Quiero fusionar dos o más archivos .wav en uno y luego convertirlo en .mp3 y esto me gustaría hacerlo en Swift (o al menos tener la opción de incluirlo en swift project).

Combinar dos archivos .wav en swift no es problema. Aquí está mi ejemplo. Ahora no sé cómo agregar la biblioteca cojo al proyecto swift y cómo usarlo (cómo cambiar la sintaxis de uso del código objetivo para usarlo en swift).

Me quedé atrapado en Swift, así que probé Lame Library con Objective C. Encontré un código de ejemplo para convertir .caf a .mp3, así que lo probé. Esto es lo que he intentado:

- (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 { }

Pero el resultado de esto es simplemente .mp3 con ruido.

Así que necesito arreglar mis tres problemas:

  • Crea el mp3 correcto de caf en Objective C
  • Cambia el código para usarlo para el archivo wav
  • Y cambiarlo para poder usarlo en Swift.

Sé que hay muchas preguntas sobre la codificación y conversión de mp3 en iOS, pero no puedo encontrar una con el ejemplo de Swift y no puedo encontrar un ejemplo con el código de Objective C en funcionamiento (solo el código de arriba). Gracias por la ayuda


Me gustaría publicar mi solución de trabajo porque tengo muchos pulgares hacia arriba y la respuesta de naresh no me ayuda mucho.

  1. He generado la biblioteca lame.framework de este proyecto https://github.com/wuqiong/mp3lame-for-iOS
  2. He agregado una biblioteca a mi proyecto Swift (Build Phases -> Link Binary With Libraries)
  3. He creado un contenedor para usar las funciones c en Objective C y, al enlazar el encabezado, lo uso en Swift.
  4. Para los archivos wav de concatenación, uso AVAssetExportSession con Swift

Y ahora los códigos fuente. Así que la primera envoltura. Es una clase para convertir archivos .wav a .mp3. Podría haber muchos cambios (quizás un parámetro para el archivo de salida y otras opciones) pero creo que todos podrían cambiarlo. Supongo que esto podría reescribirse a Swift pero no estaba seguro de cómo hacerlo. Así que es la clase de Objetivo C:

#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]; } }

Clase Swift AudioHelper para concatenar archivos de audio y método de llamada para convertir archivos .wav a .mp3:

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) } }

El encabezado puente contiene:

#import "lame/lame.h" #import "AudioWrapper.h"