2011-02-14 3 views
3

Quel serait le meilleur moyen de redimensionner une vidéo enregistrée par l'utilisateur sur l'iPhone?iOS: Redimensionner/Recadrer la vidéo enregistrée

J'ai actuellement la possibilité d'obtenir des données vidéo de deux façons:

1) Obtenir l'URL du fichier de UIImagePickerController après que la vidéo a été enregistrée

2) Obtenir les images de la vidéo comme étant Pour 1) J'aurais besoin de quelque chose qui peut lire les fichiers .mov h.264 et cracher des images individuelles. Existe-t-il une telle chose? Pour 2) J'ai pensé à obtenir un UIImage pour chaque image, redimensionner l'image et ensuite recompiler une vidéo avec quelque chose comme AVAssetWriter. Mais cela semble être une opération très intensive et je me demande s'il existe une meilleure façon d'aborder ce problème.

L'idée générale est-elle de redimensionner les vidéos pour redimensionner chaque image individuelle et ensuite recompiler une vidéo? Ou y a-t-il un moyen de redimensionner directement une vidéo entière?

J'ai simplement besoin de l'utilisateur pour enregistrer une vidéo, puis pour redimensionner cette vidéo en 320x320, pas d'édition fantaisie.

Merci pour toute aide que vous pouvez fournir.

Editer: Peut-être que 'redimensionner' est le mauvais mot. Je ai juste besoin de recadrer la vidéo de sorte qu'il va de 480x360 à 320x320. Aussi ce recadrage n'a pas besoin d'arriver en temps réel, je peux le faire une fois la vidéo enregistrée.

Répondre

3

L'alternative 2 ne fonctionnera pas en temps réel.

Pour la variante 1, utilisez AVAssetExportSession initialisé avec l'un des préréglages souhaités - par exemple AVAssetExportPreset640x480. Expérience avec AVAssetExportPresetLowQuality, AVAssetExportPresetMediumQuality, AVAssetExportPresetHighestQuality pour des résolutions supplémentaires. Notez que les fichiers vidéo ont généralement des formats 16: 9 (ou 4: 3), donc 320x320 n'est pas une option valide. Il n'y a pas de bonnes raisons pour le redimensionnement à d'autres résolutions que celles prises en charge, à moins que vous ne prévoyiez de les distribuer à d'autres téléphones, auquel cas le transcodage côté serveur est disponible.

+0

Je suis capable d'obtenir une vidéo enregistrée directement dans l'un de ces préréglages. Ce que je cherche est un moyen de recadrer la vidéo à une taille personnalisée qui ne fait pas partie de ces préréglages. Est-il impossible de recadrer une vidéo sur une dimension personnalisée, comme vous le feriez avec des images? – nebs

+0

désolé, j'ai raté la partie «récolte». Je pense que les formats vidéo ne sont pas aussi flexibles en taille que les images, c'est-à-dire que les mobiles ne supportent que certaines résolutions. Le recadrage est en général moche et je ne le recommande pas, utilisez plutôt un rembourrage si vous avez besoin de changer le rapport d'aspect. – ThomasRS

3

Dans le cas où quelqu'un court à travers cela, j'ai trouvé que vous pouvez le faire avec AVFoundation si vous nous un AVMutableVideoComposition ainsi que d'un AVMutableComposition. Vous définissez ensuite renderSize sur la composition vidéo et cela affectera la taille de sortie de la vidéo. Vous utilisez ensuite AVMutableVideoCompositionLayerInstruction pour positionner la vidéo où vous le souhaitez. Il y a un bon article here sur commencer avec toutes ces classes et son exemple de projet a commenté le code à la fin pour l'exporter.

2

Le moyen idéal est d'utiliser AVAssetReader pour lire le fichier vidéo et d'utiliser AVAssetWriter pour écrire à nouveau ce fichier vidéo dans un nouveau fichier vidéo.vous pouvez définir un outputSetting pour l'entrée écrivain:

NSDictionary* settings = [NSDictionary dictionaryWithObjectsAndKeys: 
            AVVideoCodecH264, AVVideoCodecKey, 
            [NSNumber numberWithInt: 480], AVVideoWidthKey, 
            [NSNumber numberWithInt: 480], AVVideoHeightKey, 
             AVVideoScalingModeResizeAspectFill,AVVideoScalingModeKey, 
            nil]; 
     NSLog(@"%@",[assetVideoTrack mediaType]); 
assetWriterVideoInput = [AVAssetWriterInput assetWriterInputWithMediaType: [assetVideoTrack mediaType] 
                    outputSettings:settings]; 
     [assetWriter addInput:assetWriterVideoInput]; 

vous recherchez la documentation développeur Apple pour trouver la ligne guid sur les AVAssetReader

0

Vous devez prendre l'orientation vidéo en compte. Voici une solution Swift 2. Il les deux cultures et échelles la vidéo

extension AVAsset { 

    private var g_naturalSize: CGSize { 
    return tracksWithMediaType(AVMediaTypeVideo).first?.naturalSize ?? .zero 
    } 

    var g_correctSize: CGSize { 
    return g_isPortrait ? CGSize(width: g_naturalSize.height, height: g_naturalSize.width) : g_naturalSize 
    } 

    var g_isPortrait: Bool { 
    let portraits: [UIInterfaceOrientation] = [.Portrait, .PortraitUpsideDown] 
    return portraits.contains(g_orientation) 

    // Same as UIImageOrientation 
    var g_orientation: UIInterfaceOrientation { 
    guard let transform = tracksWithMediaType(AVMediaTypeVideo).first?.preferredTransform else { 
     return .Portrait 
    } 

    switch (transform.tx, transform.ty) { 
    case (0, 0): 
     return .LandscapeRight 
    case (g_naturalSize.width, g_naturalSize.height): 
     return .LandscapeLeft 
    case (0, g_naturalSize.width): 
     return .PortraitUpsideDown 
    default: 
     return .Portrait 
    } 
    } 
} 

Voici comment obtenir la transformation

func transform(avAsset: AVAsset, scaleFactor: CGFloat) -> CGAffineTransform { 
    let offset: CGPoint 
    let angle: Double 

    switch avAsset.g_orientation { 
    case .LandscapeLeft: 
     offset = CGPoint(x: avAsset.g_correctSize.width, y: avAsset.g_correctSize.height) 
     angle = M_PI 
    case .LandscapeRight: 
     offset = CGPoint.zero 
     angle = 0 
    case .PortraitUpsideDown: 
     offset = CGPoint(x: 0, y: avAsset.g_correctSize.height) 
     angle = -M_PI_2 
    default: 
     offset = CGPoint(x: avAsset.g_correctSize.width, y: 0) 
     angle = M_PI_2 
    } 

    let scale = CGAffineTransformMakeScale(scaleFactor, scaleFactor) 
    let translation = CGAffineTransformTranslate(scale, offset.x, offset.y) 
    let rotation = CGAffineTransformRotate(translation, CGFloat(angle)) 

    return rotation 
    } 

Et comment l'utiliser dans l'instruction de la couche

let layer = AVMutableVideoCompositionLayerInstruction(assetTrack: track) 
layer.setTransform(transform(avAsset, scaleFactor: 0.8), atTime: kCMTimeZero) 

Référence

Questions connexes