Question

Utilisation du nouveau cadre de la bibliothèque d'actifs disponible dans iOS 4 je vois que je peux obtenir l'URL pour une vidéo donnée en utilisant le UIImagePickerControllerReferenceURL. L'URL est retournée dans le format suivant:

assets-library://asset/asset.M4V?id=1000000004&ext=M4V

Je suis en train de télécharger cette vidéo sur un site Web afin comme une preuve rapide de concept que je suis en train les

NSData *data = [NSData dataWithContentsOfURL:videourl];
[data writeToFile:tmpfile atomically:NO];

Les données sont jamais initialisé dans ce cas. Quelqu'un at-il réussi à accéder à l'URL directement via la nouvelle bibliothèque d'actifs? Merci pour votre aide.

Était-ce utile?

La solution

Voici une solution rapide propre pour obtenir des vidéos comme NSData. Il utilise le cadre de Photos comme ALAssetLibrary est obsolète iOS9:

  

IMPORTANT

     

Le cadre Bibliothèque actifs est obsolète iOS 9.0. Au lieu de cela, utilisez le cadre de photos à la place, qui dans iOS 8.0 et fournit plus tard plus de fonctionnalités et de meilleures performances pour travailler avec la bibliothèque de photos d'un utilisateur. Pour plus d'informations, voir des photos Cadre de référence.

import Photos

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
    self.dismissViewControllerAnimated(true, completion: nil)

    if let referenceURL = info[UIImagePickerControllerReferenceURL] as? NSURL {
        let fetchResult = PHAsset.fetchAssetsWithALAssetURLs([referenceURL], options: nil)
        if let phAsset = fetchResult.firstObject as? PHAsset {
            PHImageManager.defaultManager().requestAVAssetForVideo(phAsset, options: PHVideoRequestOptions(), resultHandler: { (asset, audioMix, info) -> Void in
                if let asset = asset as? AVURLAsset {
                    let videoData = NSData(contentsOfURL: asset.URL)

                    // optionally, write the video to the temp directory
                    let videoPath = NSTemporaryDirectory() + "tmpMovie.MOV"
                    let videoURL = NSURL(fileURLWithPath: videoPath)
                    let writeResult = videoData?.writeToURL(videoURL, atomically: true)

                    if let writeResult = writeResult where writeResult {
                        print("success")
                    }
                    else {
                        print("failure")
                    }
                }
            })
        }
    }
}

Autres conseils

J'utilise la catégorie suivante sur ALAsset:

static const NSUInteger BufferSize = 1024*1024;

@implementation ALAsset (Export)

- (BOOL) exportDataToURL: (NSURL*) fileURL error: (NSError**) error
{
    [[NSFileManager defaultManager] createFileAtPath:[fileURL path] contents:nil attributes:nil];
    NSFileHandle *handle = [NSFileHandle fileHandleForWritingToURL:fileURL error:error];
    if (!handle) {
        return NO;
    }

    ALAssetRepresentation *rep = [self defaultRepresentation];
    uint8_t *buffer = calloc(BufferSize, sizeof(*buffer));
    NSUInteger offset = 0, bytesRead = 0;

    do {
        @try {
            bytesRead = [rep getBytes:buffer fromOffset:offset length:BufferSize error:error];
            [handle writeData:[NSData dataWithBytesNoCopy:buffer length:bytesRead freeWhenDone:NO]];
            offset += bytesRead;
        } @catch (NSException *exception) {
            free(buffer);
            return NO;
        }
    } while (bytesRead > 0);

    free(buffer);
    return YES;
}

@end

Ce n'est pas la meilleure façon de le faire. Je réponds à cette question dans le cas où un autre utilisateur de SO est sur la même question.

En gros mon besoin était de pouvoir spouler le fichier vidéo dans un fichier tmp pour que je puisse le télécharger sur un site Web en utilisant ASIHTTPFormDataRequest. Il y a probablement un moyen de streaming à partir de l'url atout pour le téléchargement ASIHTTPFormDataRequest mais je ne pouvais pas comprendre. Au lieu de cela, j'ai écrit la fonction suivante pour supprimer le fichier dans un fichier tmp ajouter à ASIHTTPFormDataRequest.

+(NSString*) videoAssetURLToTempFile:(NSURL*)url
{

    NSString * surl = [url absoluteString];
    NSString * ext = [surl substringFromIndex:[surl rangeOfString:@"ext="].location + 4];
    NSTimeInterval ti = [[NSDate date]timeIntervalSinceReferenceDate];
    NSString * filename = [NSString stringWithFormat: @"%f.%@",ti,ext];
    NSString * tmpfile = [NSTemporaryDirectory() stringByAppendingPathComponent:filename];

    ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
    {

        ALAssetRepresentation * rep = [myasset defaultRepresentation];

        NSUInteger size = [rep size];
        const int bufferSize = 8192;

        NSLog(@"Writing to %@",tmpfile);
        FILE* f = fopen([tmpfile cStringUsingEncoding:1], "wb+");
        if (f == NULL) {
            NSLog(@"Can not create tmp file.");
            return;
        }

        Byte * buffer = (Byte*)malloc(bufferSize);
        int read = 0, offset = 0, written = 0;
        NSError* err;
        if (size != 0) {
            do {
                read = [rep getBytes:buffer
                          fromOffset:offset
                              length:bufferSize 
                               error:&err];
                written = fwrite(buffer, sizeof(char), read, f);
                offset += read;
            } while (read != 0);


        }
        fclose(f);


    };


    ALAssetsLibraryAccessFailureBlock failureblock  = ^(NSError *myerror)
    {
        NSLog(@"Can not get asset - %@",[myerror localizedDescription]);

    };

    if(url)
    {
        ALAssetsLibrary* assetslibrary = [[[ALAssetsLibrary alloc] init] autorelease];
        [assetslibrary assetForURL:url 
                       resultBlock:resultblock
                      failureBlock:failureblock];
    }

    return tmpfile;
}

Il vous allez ...

AVAssetExportSession* m_session=nil;

-(void)export:(ALAsset*)asset withHandler:(void (^)(NSURL* url, NSError* error))handler
{
    ALAssetRepresentation* representation=asset.defaultRepresentation;
    m_session=[AVAssetExportSession exportSessionWithAsset:[AVURLAsset URLAssetWithURL:representation.url options:nil] presetName:AVAssetExportPresetPassthrough];
    m_session.outputFileType=AVFileTypeQuickTimeMovie;
    m_session.outputURL=[NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%f.mov",[NSDate timeIntervalSinceReferenceDate]]]];
    [m_session exportAsynchronouslyWithCompletionHandler:^
     {
         if (m_session.status!=AVAssetExportSessionStatusCompleted)
         {
             NSError* error=m_session.error;
             m_session=nil;
             handler(nil,error);
             return;
         }
         NSURL* url=m_session.outputURL;
         m_session=nil;
         handler(url,nil);
     }];
}

Vous pouvez utiliser une touche de préréglage différent si vous souhaitez ré-encoder le film (AVAssetExportPresetMediumQuality par exemple)

Voici le Objectif C solution de Alonzo réponse, cadre photos à l'aide

  -(NSURL*)createVideoCopyFromReferenceUrl:(NSURL*)inputUrlFromVideoPicker{

        NSURL __block *videoURL;
        PHFetchResult *phAssetFetchResult = [PHAsset fetchAssetsWithALAssetURLs:@[inputUrlFromVideoPicker ] options:nil];
        PHAsset *phAsset = [phAssetFetchResult firstObject];
        dispatch_group_t group = dispatch_group_create();
        dispatch_group_enter(group);

        [[PHImageManager defaultManager] requestAVAssetForVideo:phAsset options:nil resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) {

            if ([asset isKindOfClass:[AVURLAsset class]]) {
                NSURL *url = [(AVURLAsset *)asset URL];
                NSLog(@"Final URL %@",url);
                NSData *videoData = [NSData dataWithContentsOfURL:url];

                // optionally, write the video to the temp directory
                NSString *videoPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%f.mp4",[NSDate timeIntervalSinceReferenceDate]]];

                videoURL = [NSURL fileURLWithPath:videoPath];
                BOOL writeResult = [videoData writeToURL:videoURL atomically:true];

                if(writeResult) {
                    NSLog(@"video success");
                }
                else {
                    NSLog(@"video failure");
                }
                 dispatch_group_leave(group);
                // use URL to get file content
            }
        }];
        dispatch_group_wait(group,  DISPATCH_TIME_FOREVER);
        return videoURL;
    }

de la réponse de Zoul merci

Similar Code in Xamarin C#

Xamarin C # équivalent

IntPtr buffer = CFAllocator.Malloc.Allocate(representation.Size);
NSError error;
            nuint buffered = representation.GetBytes(buffer, Convert.ToInt64(0.0),Convert.ToUInt32(representation.Size),out error);

            NSData sourceData = NSData.FromBytesNoCopy(buffer,buffered,true);
            NSFileManager fileManager = NSFileManager.DefaultManager;
            NSFileAttributes attr = NSFileAttributes.FromDictionary(NSDictionary.FromFile(outputPath));
            fileManager.CreateFile(outputPath, sourceData,attr);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top