2010-12-28 5 views
12

iOS 4で利用できる新しいアセットライブラリフレームワークを使用すると、UIImagePickerControllerReferenceURLを使用して特定の動画のURLを取得できることがわかります。コンセプトの迅速な証拠は私がで初期化されることはありません、以下ALAssetからビデオを取得する

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

データをしようとしていますように、私はウェブサイトにこの動画をアップロードしようとしています

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

:返されたURLは、次の形式でありますこの場合。誰も新しいアセットライブラリを介してURLに直接アクセスできましたか?ご協力いただきありがとうございます。

+0

Richさんが提案したオプションを試しましたが、うまくいきません。 テスト用にiPhoneライブラリに保存されているのと同じビデオを使用しています。返される情報辞書には、UIImagePickerControllerReferenceURLのみが含まれることがあります。私は、そのURLをvideoAssetURLToTempFileの入力として使用しようとしましたが、そのメソッドを実行すると、結果ブロックを更新するコードに入力されません。 UIImagePickerController didFinishPickingMediaWithInfoデリゲートメソッドがどのような状況で適切に機能するかはわかりません。いくつか助けてください? ありがとうございます! –

+0

これはiOSのバージョンの問題である可能性がありますか? UIImagePickerControllerReferenceURLは、データを返す古いメソッドです。 –

答えて

9

ここでは、 NSData。

重要

資産ライブラリのフレームワークはiOSの9.0から非推奨になりました: それはALAssetLibraryはiOS9で廃止される写真のフレームワークを使用しています。その代わりに、代わりにPhotosフレームワークを使用してください.iOS 8.0以降では、ユーザーの写真ライブラリを使用するための機能とパフォーマンスが向上しています。詳細については、「フォトフレームワークリファレンス」を参照してください。ここで

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

これは、これを行う最善の方法ではありません。私は別のSOユーザーが同じ問題を抱えている場合にこの質問に答えています。

基本的に私の必要性は、ASIHTTPFormDataRequestを使ってウェブサイトにアップロードできるように、ビデオファイルをtmpファイルにスプールできるようにすることでした。アセットURLからASIHTTPFormDataRequestアップロードへのストリーミング方法はおそらくありますが、わかりませんでした。代わりに、ASIHTTPFormDataRequestに追加するファイルをtmpファイルにドロップする次の関数を記述しました。

私は ALAssetで、次のカテゴリに使用
+(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; 
} 
+0

FYI:あなたは 'バッファ'を漏らしています。 – randallmeadows

+0

あなたは正しいです、ありがとうございます。 –

+0

@RichDominelli、素敵なスニペット!ありがとうございました!!! – Suran

22

:あなたは再エンコードしたい場合は、別のプリセットキーを使用することができます

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

...あなたが行くあり

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 
+0

ありがとうございます! –

+0

これは、私が探しているものです。ありがとうございました。@ zoul – fyasar

10

を映画(AVAssetExportPresetMediumQualityなど)

+1

アセット自体はどうやって手に入りましたか分かりませんでしたか? – Dejell

+0

おそらく遅すぎますが、 - [ALAssetLibrary assetForURL:resultBlock:failureBlock:]メソッドを使用して、参照URLからALAssetオブジェクトをインスタンス化できます。 – jpm

+0

回答を受け入れる必要があります。しかし、exportAsynchronouslyWithCompletionHandlerをメインスレッドにディスパッチすることを忘れないでください。デフォルトではバックグラウンドで実行されるためです。 – faviomob

1

Zoulの回答から、この写真のフレームワークに 感謝

Similar Code in Xamarin C# 

Xamarin、C#の等価を

-(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; 
    } 
0

を使用してアロンゾ答えのObjective Cのソリューションは、ある

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); 
関連する問題