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

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

新規登録して質問してみよう
ただいま回答率
85.47%
RxSwift

RxSwiftは、Reactive ExtensionsのSwift向けの実装です。iOS開発に用いられ、リアクティブプログラミングを可能にします。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

0回答

1081閲覧

[助けて]PHPickerViewControllerで選んだ動画が再生できない[もう無理]

shihominorth

総合スコア46

RxSwift

RxSwiftは、Reactive ExtensionsのSwift向けの実装です。iOS開発に用いられ、リアクティブプログラミングを可能にします。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2021/12/01 11:28

前提・実現したいこと

PHPickerViewControllerで選んだ動画から、urlを取り出し、それを再生したい。

流れ

  1. PHPickerViewControllerに偏移し、動画が選ばれたら、URLを抽出し、それをPublishSubjectで流す。

*RxSwift関連のDelegateProxyを使っています。おそらくこのurlを渡すことについては問題はないと思いますが一応記述します。
0. そのurlを受け取り、動画を再生するViewControllerに対応するViewModelに渡し、偏移する。
0. 動画を再生するUIView(=PlayVideoView)のセットアップをする。(viewdidload内で)
0. ループ再生がしたいので、AVQueuePlayer、AVPlayerLooperとAVPlayerLayerを初期化そしてそれらのフレームの大きさなどのセットアップをする。(viewdidload内で)
0. PlayVideoView内のactivitiy indicatorのアニメーションをスタート、準備ができたらストップ
0. 動画再生(コード内ではviewdidappear内で行なっていますが、どこでも大丈夫だと思います。ただし該当のViewcontollerに偏移されたら直ぐに再生したいです。)

発生している問題・エラーメッセージ

 まず全く再生される気配すらありません。AVPlayer.status, VPlayer.currentItem.statusとAVPlayerItemNewErrorLogEntry, AVPlayerItemFailedToPlayToEndTime, AVPlayerItemPlaybackStalled(これは関係なさそう)にオブザーバーを追加していますがどのオブザーバーも発動しません。そして何らかのエラーメッセージも表示されません。
またコードを直していく過程でAVQueuePlayerがnilになっていたので、それを直しました。よってAVQueuePlayerがnilであることは原因ではありません。

試したこと

別の簡易のProjectを作り同じ動画を選択して、再生したのですがそれは成功したのでURLが再生できないというわけではなさそうです。もしかして何かのタイミングが原因なのかもしません。

参考URL

https://stackoverflow.com/a/58800860

該当のソースコード

Swift

1 2import UIKit 3import AVKit 4import RxSwift 5import RxCocoa 6 7class UploadingVideoViewController: UIViewController, BindableType { 8 9 typealias ViewModelType = UploadingVideoVM 10 var viewModel: UploadingVideoVM! 11 12 var playView: PlayVideoView! 13 let loop = VideoPlayerLooped() 14 15 override func viewDidLoad() { 16 <省略> 17 18 setUpPlayVideoView() 19 20 } 21 22 override func viewDidAppear(_ animated: Bool) { 23 24 self.loop.playVideo(url: self.viewModel.url, inView: self.playView) 25 26 } 27 28 func setUpPlayVideoView() { 29 30 self.playView = PlayVideoView() 31 playView.frame = view.bounds 32 33 setUpBackBtn() 34 setUpAddBtn() 35 setUpSlider() 36 setUpGestureRecognizer() 37 38 view.addSubview(self.playView) 39 40 let interval = CMTime(value: 1, timescale: 2) 41 42 self.videoPlayer?.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main) { [unowned self] progressTime in 43 44 if let duration = self.videoPlayer?.currentItem?.duration { 45 46 let seconds = CMTimeGetSeconds(progressTime) 47 let durationSeconds = CMTimeGetSeconds(duration) 48 self.playView.slider.value = Float(seconds / durationSeconds) 49 50 } 51 } 52 53 NotificationCenter.default.addObserver(self, selector: #selector(itemNewErrorLogEntry), name: .AVPlayerItemNewErrorLogEntry, object: nil) 54 55 NotificationCenter.default.addObserver(self, selector: #selector(itemFailedToPlayToEndTime), name: .AVPlayerItemFailedToPlayToEndTime, object: nil) 56 57 NotificationCenter.default.addObserver(self, selector: #selector(itemPlaybackStalled), name: .AVPlayerItemPlaybackStalled, object: nil) 58 59 self.videoPlayer?.addObserver(self, forKeyPath: #keyPath(AVPlayer.status), options: [.new, .initial], context: nil) 60 self.videoPlayer?.addObserver(self, forKeyPath: #keyPath(AVPlayer.currentItem.status), options:[.new, .initial], context: nil) 61 62 63 } 64 65 66 67 func setUpBackBtn() { 68 <省略> 69 self.playView.backBtn.setTitle("", for: .normal)など 70 71 } 72 73 74 func setUpAddBtn() { 75 <省略> 76 77 } 78 79 func setUpSlider() { 80 81 self.playView.slider.rx.controlEvent(.valueChanged) 82 .catch { err in 83 return .empty() 84 } 85 .subscribe(onNext: { [unowned self] in 86 87 if let duration = self.videoPlayer?.currentItem?.duration { 88 89 let totalSeconds = CMTimeGetSeconds(duration) 90 let value = Float64(self.playView.slider.value) * totalSeconds 91 let seekTime = CMTime(value: Int64(value), timescale: 1) 92 93 94 videoPlayer?.seek(to: seekTime, completionHandler: { isCompleted in 95 96 }) 97 } 98 99 }) 100 .disposed(by: viewModel.disposeBag) 101 } 102 103 104 105 fileprivate func setUpGestureRecognizer() { 106 107 <省略> 108 } 109 110 @objc func itemPlaybackStalled() { 111 print("AVPlayerItemNewErrorLogEntry") 112 } 113 114 @objc func itemNewErrorLogEntry() { 115 print("itemNewErrorLogEntry") 116 } 117 118 119 @objc func itemFailedToPlayToEndTime() { 120 print("failed") 121 } 122 func playVideo(url: URL, inView: UIView){ 123 124 let playerItem = AVPlayerItem(url: url) 125 126 videoPlayer = AVQueuePlayer(items: [playerItem]) 127 playerLooper = AVPlayerLooper(player: videoPlayer!, templateItem: playerItem) 128 129 videoPlayerLayer = AVPlayerLayer(player: videoPlayer) 130 videoPlayerLayer!.frame = inView.bounds 131 videoPlayerLayer!.videoGravity = .resizeAspectFill 132 133 inView.layer.addSublayer(videoPlayerLayer!) 134 135 136 137 videoPlayer?.play() 138 139 } 140 141 func remove() { 142 videoPlayerLayer?.removeFromSuperlayer() 143 144 } 145 146 override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { 147 148     <省略> 149 150if let _ = object as? AVPlayer { 151 152 if keyPath == #keyPath(AVPlayer.currentItem.status) { 153 154 let newStatus: AVPlayerItem.Status 155 if let newStatusAsNumber = change?[NSKeyValueChangeKey.newKey] as? NSNumber { 156 newStatus = AVPlayerItem.Status(rawValue: newStatusAsNumber.intValue)! 157 } else { 158 newStatus = .unknown 159 } 160 if newStatus == .failed { 161 NSLog("Error: (String(describing: self.videoPlayer?.currentItem?.error?.localizedDescription)), error: (String(describing: self.videoPlayer?.currentItem?.error))") 162 } 163 } 164 165 } 166 167 } 168} 169

Swift

1 2class PlayVideoView: UIView { 3 4 5 6 let indicator: UIActivityIndicatorView = { 7 8 let result = UIActivityIndicatorView() 9 <省略> 10 return result 11 }() 12 13 14 @IBOutlet weak var backBtn: UIButton! 15 @IBOutlet weak var addBtn: UIButton! 16 @IBOutlet weak var slider: UISlider! 17 18 19 override init(frame: CGRect) { 20 super.init(frame: frame) 21 <省略> 22 23 } 24 25 required init?(coder aDecoder: NSCoder) { 26 super.init(coder: aDecoder)! 27 loadNib() 28 29 } 30 31 32 <省略> 33 34} 35

Swift

1import Foundation 2import AVKit 3 4class VideoPlayerLooped { 5 6 public var videoPlayer:AVQueuePlayer? 7 public var videoPlayerLayer:AVPlayerLayer? 8 var playerLooper: NSObject? 9 var queuePlayer: AVQueuePlayer? 10 11 func playVideo(url: URL, inView: UIView){ 12 13 let playerItem = AVPlayerItem(url: url) 14 15 videoPlayer = AVQueuePlayer(items: [playerItem]) 16 playerLooper = AVPlayerLooper(player: videoPlayer!, templateItem: playerItem) 17 18 videoPlayerLayer = AVPlayerLayer(player: videoPlayer) 19 videoPlayerLayer!.frame = inView.bounds 20 videoPlayerLayer!.videoGravity = AVLayerVideoGravity.resizeAspectFill 21 22 inView.layer.addSublayer(videoPlayerLayer!) 23 24 if let indicator = inView.subviews.first(where: { $0 is UIActivityIndicatorView }) as? UIActivityIndicatorView { 25 26 indicator.stopAnimating() 27 28 } 29 30 videoPlayer?.play() 31 32 } 33 34 func remove() { 35 videoPlayerLayer?.removeFromSuperlayer() 36 37 } 38} 39

補足情報(FW/ツールのバージョンなど)

Xcode 13.1 Swift 5

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

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

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

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

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

1T2R3M4

2021/12/01 13:07

無理ならば自分で作るのはあきらめて、誰かに有償で頼めばいいのでは。
shihominorth

2021/12/01 13:30

とりあえずやれることはやってみてそれから頼んでみます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問