1
0

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 1 year has passed since last update.

[Swift]骨格検出アプリ作成 備忘録 1.動画を読み込ませるようにする

Posted at

骨格検出アプリ作成 1

動画の読み込ませが完了したので、記録を残しておきたいと思います。
(もっと良い方法があれば知りたいです。)

できたもの

douga_select.gif

Qiitaでの動画投稿不慣れで見づらく申し訳ないです。

やったこと

動画再生用のViewを用意しました

class PlayerView: UIView {
    // The player assigned to this view, if any.
    var videoPlayer: AVPlayer? {
        get { return playerLayer.player }
        set { playerLayer.player = newValue }
    }
    // The layer used by the player.
    var playerLayer: AVPlayerLayer {
        return layer as! AVPlayerLayer
    }
    // Set the class of the layer for this view.
    override static var layerClass: AnyClass {
        return AVPlayerLayer.self
    }
}

iPhone内の動画を選択するコードを用意しました(selectボタンクリックで動作する)

// selectボタンクリック時の動作設定
    @IBAction func buttonClick(_ sender: Any) {
        
        // カメラロール設定
        var configuration = PHPickerConfiguration()
        configuration.selectionLimit = 1 // 選択数
        //configuration.filter = .images // 写真
        configuration.filter = .videos // 動画
        configuration.preferredAssetRepresentationMode = .current // これがないとJPEGが選択できなかった
        let picker = PHPickerViewController(configuration: configuration)
        picker.delegate = self
        
        // アクセス許可ステータス
        switch PHPhotoLibrary.authorizationStatus(for: .addOnly) {
            // 未設定
        case .notDetermined:
            // アクセス許可をリクエスト
            PHPhotoLibrary.requestAuthorization(for: .addOnly) {status in
                switch status {
                    // カメラロール表示
                case .authorized:
                    DispatchQueue.main.async { // UIの更新
                        self.present(picker, animated: true, completion: nil)
                    }
                    // カメラへのアクセスを拒否
                default:
                    print("denied")
                }
            }
            
            // カメラロール表示
        case .authorized:
            DispatchQueue.main.async {  // UIの更新
                self.present(picker, animated: true)
            }
            
            // カメラへのアクセスが拒否されている
        case .denied:
            // ダイアログを表示する
            let alert = UIAlertController(title: "写真にアクセスできません", message: "設定からアクセス許可をしてください", preferredStyle: .alert)
            let settings = UIAlertAction(title: "設定", style: .default, handler: { (_) -> Void in
                let settingsURL = URL(string: UIApplication.openSettingsURLString)
                UIApplication.shared.open(settingsURL!, options: [:], completionHandler: nil)
            })
            let close: UIAlertAction = UIAlertAction(title: "キャンセル", style: .cancel, handler: nil)
            alert.addAction(settings)
            alert.addAction(close)
            self.present(alert, animated: true, completion: nil)
            
            // 本体から制限されていて、アプリのアクセス許可を変更できない
        case .restricted:
            // ダイアログを表示する
            let alert = UIAlertController(title: "写真にアクセスできません", message: "", preferredStyle: .alert)
            let close: UIAlertAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
            alert.addAction(close)
            self.present(alert, animated: true, completion: nil)
            
            // デフォルトの場合はbreak
        default: break
        }
    }

// ビデオ選択の関数
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        picker.dismiss(animated: true, completion: nil)
        guard let provider = results.first?.itemProvider else {
            return
        }
        guard let typeIdentifier = provider.registeredTypeIdentifiers.first else { return }
        
        if provider.hasItemConformingToTypeIdentifier(typeIdentifier) {
            provider.loadFileRepresentation(forTypeIdentifier: typeIdentifier){ [weak self] (url, error) in
                //if let url = url as? URL {
                if let url = url {
                    let avAsset = AVURLAsset(url: url)
                    // AVPlayerに再生させるアイテムを生成.
                    self?.playerItem = AVPlayerItem(asset: avAsset)
                    
                    // AVPlayerを生成.
                    self?.videoPlayer = AVPlayer(playerItem: self?.playerItem)
                    self?.playerView.videoPlayer = self?.videoPlayer
                    self?.setupPlayer()
                }
            }
        }
        picker.dismiss(animated: true) // カメラロールを閉じる
    }

あとはseekBar、再生/停止ボタンを用意しました。

調整項目

スライダーの設定コード

// スライダーの同期
    @IBAction func onSliderValueChange(_ sender: UISlider) {
        removePeriodicTimeObserver()
        videoPlayer?.pause()
        stopButoon.isEnabled = false
        startButton.isEnabled = true
        //動画の再生時間をシークバーとシンクロ-.
        videoPlayer!.seek(to: CMTimeMakeWithSeconds(Float64(seekBar.value), preferredTimescale: Int32(NSEC_PER_SEC)), toleranceBefore: CMTime.zero, toleranceAfter: CMTime.zero)
    }

// 再生に合わせてシークバーを更新
    func addPeriodicTimeObserver(){
        let timeScale = CMTimeScale(NSEC_PER_SEC)
        let time = CMTime(seconds: 0.01, preferredTimescale: timeScale)
        // if スライダーを操作している間は動かさないとか?
        timeObserverToken = videoPlayer?.addPeriodicTimeObserver(forInterval: time, queue: nil, using: { time in
            // 総再生時間を取得.
            let duration = CMTimeGetSeconds((self.videoPlayer?.currentItem!.duration)!)
            
            // 現在の時間を取得.
            let time = CMTimeGetSeconds((self.videoPlayer?.currentTime())!)
            
            // シークバーの位置を変更.
            let value = Float(self.seekBar.maximumValue - self.seekBar.minimumValue) * Float(time) / Float(duration) + Float(self.seekBar.minimumValue)
            self.seekBar.value = value
        })
    }

seekbarの設定がうまく動作していません。

エラー挙動
●スライダーを操作していくとスライダー後半で空白or動画最後のフレームが表示され続ける問題

●動画再生中にスライダーに触れるとスライダーが戻ろうとする挙動がある

原因として考えられるもの
●スライダーの最大値=動画の総再生時間をリンクさせられていない?

●スライダーに触れている設定と動画再生中にスライダーが同期しながら動く設定が噛み合っていない、片方作動時は切るようにしないといけない?

色々と悩んでいますが、未解決状態です。

今後の流れ

1.Swiftで動画を読み込ませるようにする←今回
2.読み込んだ動画に対して骨格検出を行う←次回

調整が必要な項目はありますが、メインの動画を読み込ませるところは達成できたかと思います。

次回は調整を行いつつ解決案が出れば追記しながら、メインパートの骨格検出やっていきたいと思います。

1
0
0

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?