7
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【mBaaS】NSData型で取得したデータをmp4に変換して再生する

Posted at

mBaaSのファイルストアは動画ファイルを保存することもでできます。
ただし、公開ファイルではないデータをファイルストアから取得する場合は、NSData形式で取得することになります。
imageファイルは、UIImageにinitWithDataがあるのですが、AVPlayerにはinitWithDataがないため、mp4ファイルに変換するには自分で変換する必要があります。

使用するクラス

AVPlayerViewController
AVAssetResourceLoaderDelegate
AVURLAsset
AVAssetResourceLoader
AVPlayerItem

Objective-C

mBaaSから動画データを取得して、AVPlayerViewControllerを継承したクラスに渡します。

//ファイル名の指定
NCMBFile *fileData = [NCMBFile fileWithName:@"fileName" data:nil];

//ファイルストアからファイルを取得
[fileData getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
    if (error){
        //エラー時の処理
    } else {
        //成功時の処理
        PlayerViewController *playerViewController = [[PlayerViewController alloc]init];
        playerViewController.movieData = data;
        
        [self presentViewController:playerViewController animated:YES completion:nil];
    }
}];
PlayerViewController.h
@import AVFoundation;
@import AVKit;

@interface PlayerViewController : AVPlayerViewController

@property (nonatomic) NSData *movieData;

@end
PlayerViewController.m
#import "PlayerViewController.h"

@interface PlayerViewController ()<AVAssetResourceLoaderDelegate>

@end

@implementation PlayerViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    AVURLAsset *asset = [AVURLAsset URLAssetWithURL:[NSURL URLWithString:@""] options:nil];
    
    AVAssetResourceLoader *resourceLoader = asset.resourceLoader;
    [resourceLoader setDelegate:self queue:dispatch_get_main_queue()];
    
    AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithAsset:asset];
    self.player = [AVPlayer playerWithPlayerItem:playerItem];
}

- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest {
    // 元データがmp4の場合
    loadingRequest.contentInformationRequest.contentType = @"public.mpeg-4";
    loadingRequest.contentInformationRequest.contentLength = [self.movieData length];
    loadingRequest.contentInformationRequest.byteRangeAccessSupported = YES;
    
    NSData *requestedData = [self.movieData subdataWithRange:NSMakeRange((NSUInteger)loadingRequest.dataRequest.requestedOffset,
                                                                         (NSUInteger)loadingRequest.dataRequest.requestedLength)];
    
    [loadingRequest.dataRequest respondWithData:requestedData];
    [loadingRequest finishLoading];
    
    return YES;
}

Swift

//ファイル名の指定
let fileData = NCMBFile.file(withName: "fileName", data: nil) as! NCMBFile

fileData.getDataInBackground { (data, error) in
    if error != nil {
        //エラー時の処理
    } else {
        //成功時の処理
        let playerViewController = PlayerViewController()
        playerViewController.movieData = data
        
        self.present(playerViewController, animated: true, completion: nil)
    }
}

URLは構造体なので、空文字を使うとnilとなってしまうため、NSURLをキャストしたものを使用しています。

PlayerViewController.swift
import UIKit
import AVFoundation
import AVKit

class PlayerViewController: AVPlayerViewController,AVAssetResourceLoaderDelegate {
    
    var movieData:Data? = nil
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let asset = AVURLAsset.init(url: NSURL.init(string: "")! as URL)
        
        let resourceLoader = asset.resourceLoader
        resourceLoader.setDelegate(self, queue: DispatchQueue.main)
        
        let playerItem = AVPlayerItem.init(asset: asset)
        self.player = AVPlayer (playerItem: playerItem)
    }
    
    func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool {
        
        // 元データがmp4の場合
        loadingRequest.contentInformationRequest?.contentType = "public.mpeg-4";
        loadingRequest.contentInformationRequest?.contentLength = Int64((self.movieData?.count)!)
        loadingRequest.contentInformationRequest?.isByteRangeAccessSupported = true
        
        let requestedData = self.movieData?.subdata(in: Int(loadingRequest.dataRequest!.requestedOffset) ..< Int(loadingRequest.dataRequest!.requestedLength))
        
        loadingRequest.dataRequest?.respond(with: requestedData!)
        loadingRequest.finishLoading()
        
        return true
    }
}
7
12
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?