2011-02-23 8 views
5

Estoy utilizando AVFoundation para crear un archivo de película (mp4) usando imágenes y archivos de sonido.¿Cómo agregar contenidos de archivos de audio en una película usando AVFoundation en iOS4?

He creado correctamente un archivo de película usando AVAssetWriterInputPixelBufferAdaptor que agrega CVPixelBufferRef (extraído de objetos UIImage) en un archivo de película.

Ahora, deseo agregar contenido de audio desde un archivo en esa película. La obtención de datos desde el micrófono del dispositivo no es lo que estoy pensando aquí. Y no pude encontrar nada similar a AVAssetWriterInputPixelBufferAdaptor, que puede ayudar a escribir datos de audio en ese archivo de película.

¿Falta algo aquí?

+0

Tengo un problema muy similar. En mi aplicación, he creado una película basada en un archivo de video almacenado en el directorio de rotación de la cámara (con algunos cambios realizados usando acceso directo a píxeles). Para eso he usado las clases AVAsset/AVAssetReader/AVAssetWriter y relacionadas. El único problema que tengo ahora es que mi película no contiene ninguna pista de audio, solo datos de video. Me gustaría "agregar" una pista de audio a mi película que proviene del archivo de video original. Por alguna razón no pude hacer eso cuando el video se estaba escribiendo, así que ahora estoy buscando una manera de hacerlo después de que se haya realizado la conversión de video. – peter

Respuesta

5

Al menos para mí, la solución fue utilizar la clase AVMutableComposition.

1) crear AVMutableComposition objeto de clase
2) crear 2 objetos de clase AVURLAsset, la primera basada en el archivo de vídeo, y el segundo basado en un archivo que desea extraer pistas de audio de
3) crear 2 AVMutableCompositionTrack objetos de clase, al igual que antes de que uno con pista de audio, el segundo con pista de vídeo (en base a los activos apropiados objetos a partir de 2))
4) crear clase AVAssetExportSession basado en la composición objeto a partir de 1)
5) exportar su sesión

Saludos cordiales

0

Gracias @peter. Aquí hay una solución en el código.

-(BOOL)compositeVideo{ 
    //Record cur video 
    NSURL *curAudio = [[NSBundle mainBundle]URLForResource:@"a" withExtension:@".pcm"]; 
    NSURL *curVideo = [[NSBundle mainBundle]URLForResource:@"v" withExtension:@".mp4"]; 
    AVAsset *video = [AVAsset assetWithURL:curVideo]; 
    AVAsset *audio = [AVAsset assetWithURL:curAudio]; 
    AVAssetTrack *vTrack = [[video tracksWithMediaType:AVMediaTypeVideo] firstObject]; 
    NSArray *arr = [audio tracksWithMediaType:AVMediaTypeAudio]; 
    AVAssetTrack *aTrack = [arr firstObject]; 

    AVMutableComposition *composition = [AVMutableComposition composition]; 
    AVMutableCompositionTrack *visualTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:1]; 
    AVMutableCompositionTrack *audioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; 
    NSError *error; 
    [visualTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, video.duration) ofTrack:vTrack atTime:kCMTimeZero error:&error]; 
    if (error) { 
     NSLog(@"video composition failed! error:%@", error); 
     return NO; 
    } 
    [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, audio.duration) ofTrack:aTrack atTime:kCMTimeZero error:&error]; 
    if (error) { 
     NSLog(@"audio composition failed! error:%@", error); 
     return NO; 
    } 

    AVAssetExportSession *exporter = [AVAssetExportSession exportSessionWithAsset:composition presetName:AVAssetExportPresetHighestQuality]; 
    NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject; 
    exporter.outputURL = [NSURL fileURLWithPath:[path stringByAppendingPathComponent:@"compositedVideo.mp4"]]; 
    [[NSFileManager defaultManager] removeItemAtPath:path error:nil]; 
    exporter.outputFileType = AVFileTypeQuickTimeMovie; 
    [exporter exportAsynchronouslyWithCompletionHandler:^{ 
     if (exporter.error) { 
      NSLog(@"exporter synthesization failed! error:%@", error); 
      [self.delegate compositeDidFinishAtURL:nil duration:-1]; 
     }else{ 
      [self.delegate compositeDidFinishAtURL:exporter.outputURL duration:CMTimeGetSeconds(video.duration)]; 
     } 
    }]; 
    return YES; 
} 
Cuestiones relacionadas