質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Swift 2

Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

Q&A

解決済

1回答

4609閲覧

Swiftで動画をMP4に変換したい

daigakusei

総合スコア18

Swift 2

Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

0グッド

0クリップ

投稿2016/06/26 08:17

編集2016/06/30 08:35

Swiftでカメラロールにある動画を取り出した(~.movの)ものをmp4に変換したいと思い調べていると、
下記の記事を見つけて実装してみましたが変換がうまくいかなかったので質問させていただきました。
Swift で録画したビデオ(mov)を MP4 に変換する

コード内の moviePath はString型で既にカメラロールから選択した動画のパスが入っている状態です。

Swift

1// mp4変換 2 let filename = "testVideo.mp4" 3 4 let filePath = NSTemporaryDirectory().stringByAppendingString(filename) 5 let outputURL = NSURL(fileURLWithPath: filePath) 6 7 let myUrl: NSURL = NSURL(string: moviePath)! 8 let avAsset = AVURLAsset(URL: myUrl, options: nil) 9 let exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetPassthrough) 10 11 exportSession!.outputFileType = AVFileTypeMPEG4 // ファイルタイプの指定 12 exportSession!.outputURL = outputURL // 保管場所を指定 13 14exportSession!.exportAsynchronouslyWithCompletionHandler { () -> Void in 15 do { 16 try NSFileManager.defaultManager().removeItemAtPath(filePath) 17 switch exportSession!.status { 18 case AVAssetExportSessionStatus.Completed: 19 PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL(NSURL(fileURLWithPath: self.moviePath)) 20 break 21 case AVAssetExportSessionStatus.Failed: 22 print("failed \(exportSession?.error)") 23 break 24 case AVAssetExportSessionStatus.Cancelled: 25 print("cancelled \(exportSession?.error)") 26 break 27 default: 28 break 29 } 30 } catch { 31 print("Error") 32 } 33 }

実行してもエラーはでないものの、ローカルにも保存されていません。
outputURLで管理場所を指定しているにもかかわらずその場所に~.mp4が入らない原因はなぜでしょうか。
どなたか教えていただけると助かります。

下記のコードがimagePickerController内で上記の内容を行ったものになります。

Swift

1func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) { 2 let mediaType = info[UIImagePickerControllerMediaType] as! NSString 3 if mediaType == kUTTypeMovie { 4 let urlM: NSURL = info[UIImagePickerControllerMediaURL] as! NSURL 5 } 6 7 let filePath = NSTemporaryDirectory().stringByAppendingString(filename) 8 let filename = "testVideo.mp4" 9 let outputURL = NSURL(fileURLWithPath: filePath) 10 11 let avAsset = AVURLAsset(URL: myUrl, options: nil) 12 let exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetPassthrough) 13 14 exportSession!.outputFileType = AVFileTypeMPEG4 15 exportSession!.outputURL = outputURL 16 17 exportSession!.exportAsynchronouslyWithCompletionHandler { () -> Void in 18 do { 19 try NSFileManager.defaultManager().removeItemAtPath(filePath) 20 switch exportSession!.status { 21 case AVAssetExportSessionStatus.Completed: 22 PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL(NSURL(fileURLWithPath: urlR)) // エラー 23 break 24 case AVAssetExportSessionStatus.Failed: 25 print("failed \(exportSession?.error)") 26 break 27 case AVAssetExportSessionStatus.Cancelled: 28 print("cancelled \(exportSession?.error)") 29 break 30 default: 31 break 32 } 33 } catch { 34 print("Error") 35 } 36 } 37}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

肝心の「変換/保存処理」を実装していないので保存されるわけがありません。

アルバムへの書き込み

swift

1PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL(NSURL(fileURLWithPath: self.moviePath))

↑を↓に置き換える。

swift

1PHPhotoLibrary.sharedPhotoLibrary().performChanges({ 2 let result = PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL(outputURL) 3 print(result) 4 }, completionHandler: { (completed, error) in 5 print("finished") 6})

finishedが表示されれば成功。

投稿2016/06/27 03:50

編集2016/06/30 09:44
fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

daigakusei

2016/06/29 08:14

コメントありがとうございます。 変換と保存処理というのはどのように実装すればよいでしょうか? 私はてっきり exportSession!.outputFileType = AVFileTypeMPEG4 このやり方が変換するものだと勘違いをしておりました(^^;) また、この質問だと丸投げになってしまうのですが、Document内に画像や文字列を保存するやり方は載っていても変換した動画ファイルを格納するやり方が調べてもよくわからなかったためどのように書けばそのようなことができるか教えていただけると助かりますm(_ _)m
daigakusei

2016/06/29 08:19

あと、申し訳ないのですが、AssetsLibraryがiOS9など非推奨なため、できればそちらを使わないやり方があればそちらで教えていただけると嬉しいです。。
fuzzball

2016/06/29 08:21 編集

>>変換と保存処理というのはどのように実装すればよいでしょうか? あなたが質問に書いているサイトの記事に書いてありますが。 そんなに長くないコードなのですから、少しは理解しようという姿勢を見せて欲しいものです。
daigakusei

2016/06/29 13:41 編集

記事の書いてあるものが理解できずにいたのでとりあえず動くように 書き換えてみましたが、catchに入ってしまうため、ローカルに保存されず変換もされていません。 どこを間違えてしまっているのでしょうか?何度も質問すみません。 ```Swift let filename = "testVideo.mp4" let filepath = NSTemporaryDirectory().stringByAppendingString(filename) let outputURL = NSURL(fileURLWithPath: filepath) let myUrl: NSURL = NSURL(string: moviePath)! let avAsset = AVURLAsset(URL: myUrl, options: nil) let exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetPassthrough) exportSession!.outputFileType = AVFileTypeMPEG4 // ファイルタイプの指定 exportSession!.outputURL = outputURL // 保管場所を指定 exportSession!.exportAsynchronouslyWithCompletionHandler { () -> Void in do { try NSFileManager.defaultManager().removeItemAtPath(filePath) switch exportSession!.status { case AVAssetExportSessionStatus.Completed: PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL(NSURL(fileURLWithPath: self.moviePath)) break case AVAssetExportSessionStatus.Failed: break case AVAssetExportSessionStatus.Cancelled: break default: break } } catch { print("Error") } } ``` コード内の moviePath はString型で既にカメラロールから選択した動画のパスが入っている状態です。 見にくくなってしまい、すみません^^;
fuzzball

2016/06/29 13:53

コードは質問欄に書いて下さい。
daigakusei

2016/06/29 14:06 編集

質問欄にコードを追加して修正いたしました。
fuzzball

2016/06/30 00:42

変換前のファイル削除(removeItemAtPath)で出てるエラーですね。 filepathの中身を教えて下さい。 あと、一度、removeItemAtPathをコメントアウトして試してみて下さい。(do~catchもコメントアウト)
daigakusei

2016/06/30 03:01

すみません、記述にミスがありました。 filepath ではなく filePath でした。ちなみに中身はこのようになっております。 NSTemporaryDirectory().stringByAppendingString("testVideo.mp4") ローカルに保存するのは一時的な動作なので /tmp に動画ファイルを入れたいと思っています。 また、do~catchとremoveItemAtPathをコメントアウトして分かったのですが、どうやら case AVAssetExportSessionStatus.Completed: には行かずに case AVAssetExportSessionStatus.Failed: に行くのがわかりました。 これは一体なぜなのでしょうか。。。
fuzzball

2016/06/30 03:09

実際にどういう値が入っているか?という質問です。 print(filePath) として出力されたログをコピペして下さい。
daigakusei

2016/06/30 04:36

こちらがfilePathを出力した際のログになります。ちなみにString型です。 /private/var/mobile/Containers/Data/Application/63919993-90A0-4B27-ABE0-AF50614D9E85/tmp/testVideo.mp4
fuzzball

2016/06/30 04:57

moviePathの値も教えて下さい。String型とのことですが、UIImagePickerControllerで取得したものではないのでしょうか?
daigakusei

2016/06/30 05:07

おっしゃる通り、UIImagePickerControllerで取得したものがmoviePathになります。 moviePathはこちらになります。こちらもString型です。 /private/var/mobile/Containers/Data/Application/357441A6-3607-4D71-8356-09EEDFE6311E/tmp/trim.75904AA6-BCB2-46DA-8283-916BA88DBA22.MOV
fuzzball

2016/06/30 05:58

UIImagePickerControllerで取得しているのでしたら、info[UIImagePickerControllerMediaURL]で直接NSURLを取れると思いますが、なぜ一旦String型にしているのでしょうか? String型にせず、そのままNSURLを渡すようにして一度試してもらえるでしょうか?
daigakusei

2016/06/30 08:19 編集

UIImagePickerControllerで取得したメソッドとは別のメソッドで行っていたというのもありまして、値を一旦グローバル変数の中に入れてから渡していたのと、そのままNSURLを渡すとErrorメッセージで Cannot convert value of type 'NSURL' to expected argument type 'String' と表示されてしまったので String型 でないといけないみたいです。。
fuzzball

2016/06/30 08:17

コードを書いて下さい。
daigakusei

2016/06/30 08:32

imagePickerController内で行った際のコードを書きました。 何度もすみません^^;
fuzzball

2016/06/30 08:54

今エラーが出ている箇所は、出力先を指定するところです。(そもそも、今はそこまで処理が行っていない) UIImagePickerControllerで取得したNSURLは入力ですから、ここで指定します。 let avAsset = AVURLAsset(URL: urlM, options: nil)
daigakusei

2016/06/30 09:35 編集

なるほど、そこに直接入れるという意味だったのですね。ありがとうございます! もう一度動かしてみると(do~catch覗いた状態で) case AVAssetExportSessionStatus.Completed: に入りました。また、removeItemAtPathのパスを間違えてしまっていたのでurlMをString型に直したものをいれたらできました。 少し勘違いをしてしまっているかもしれないのですが、こちらの処理はどのような処理をすることを指すのでしょうか? PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL
fuzzball

2016/06/30 09:43

変換したmp4ファイル(outputURL)をアルバムに書き込む処理です。 そのままでは動かないと思いますので、回答に追記しました。 試してみて下さい。
daigakusei

2016/06/30 10:27

ありがとうございます。おかげでうまくいきました! 長いことお付き合いくださり本当にありがとうございます。 最後に何度も質問してしまい申し訳ないのですが、記載されている PHPhotoLibrary.sharedPhotoLibrary().performChanges は PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL を 使用するために呼び出すものという認識でよいでしょうか??
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問