「Repete Plus」をアップデートしました。(version 7.3)

「Repete Plus」をアップデートしました。(version 7.2.3 -> version 7.3)

Repete Plusは、語学学習を支援するオーディオプレイヤーです。
無音部分を自動認識し、語学教材をフレーズごとに間隔をあけて再生できます。

App Storeはこちら

使い方を紹介しているサポートサイトはこちら
Repete Plus – nackpan Blog

変更点

Siri ショートカットで起動再生

Siriを使って起動再生する機能が、Repete Plusアプリ内部で設定できるようになりました。

設定 > 詳細 > Siri ショートカット

から 「Siriに追加」ボタンを押して、表示されたAdd to Siri画面で「Add to Siri」ボタンを押すことで、利用できます。

「Hey Siri」でSiriを呼び出し、「Repete Plusを再生」と呼びかけることで、Repete Plusの起動・再生ができます。

 タップジェスチャーに「テキストを表示する/隠す」が加わりました。

設定 > ジェスチャー > タップ > テキストを表示する/隠す

この項目を選んでテキストエリアの設定した範囲でタップすると、テキストを表示/隠すを切り替えることができます。


語学学習を助けるRepete Plusをよろしくおねがいします。

「Repete」をアップデートしました(version 6.1)

iPhone/iPadアプリ「Repete」(レペテ)(旧「語学学習支援プレイヤー」)をアップデートしました。(version 5.3 -> version 6.1)

「Repete」(「語学学習支援プレイヤー」)は、語学学習の手助けをするオーディオプレイヤーです。ファイルの無音部分を自動的に検出し、フレーズごとにあいだをおいて再生します
リピーティングに便利なオーディオプレイヤーです。

変更点

学習記録

プレイヤー画面の上部に、学習記録を表示する「記録」 ボタンがつきました。
「記録」 ボタンを押すと、学習記録を見ることができます。

学習時間
日々のおおよその学習時間(プレイヤーの再生期間)が表示されます。

Siri ショートカットで起動再生

Siriを使って起動再生する機能が、Repeteアプリ内部で設定できるようになりました。

設定 > 詳細 > Siri ショートカット

から 「Siriに追加」ボタンを押して、表示されたAdd to Siri画面で「Add to Siri」ボタンを押すことで、利用できます。

「Hey Siri」でSiriを呼び出し、「Repeteを再生」と呼びかけることで、Repeteの起動・再生ができます。


語学学習を助けるRepeteを活用いただければ幸いです。
よろしくおねがいします。

2019年11月開発状況

2019年11月。

上旬

Repete Plus 7.2.3のアップデートをおこないました。
イヤホンのボタンを押したさいに、オーディオをPlay/Pauseする機能が働いていない不具合を修正しました。

Repeteのアップデートを作成。
Appleに提出したところ、審査チームから「Siriに追加(Add to Siri)」ボタンがアプリ内にないようだとの指摘があり、どうなっているのか説明するようにとのコメントとともにメタデータリジェクトになりました。
あらたなビルドを提出する必要はないが、審査チームの指摘に対して説明をする必要があります。
回答しました。
Siriを使って起動再生できる機能を2019年3月バージョン3.8で加えました。そのさいに、iPhone設定のSiriの項目から起動再生用ショートカットを登録できるので、アプリ内には「Siriに追加(Add to Siri)」ボタンは加えませんでした。
回答して審査チームの審査待ち期間に、iPhone設定のSiriの項目を見ると、ショートカット登録の項目がなくなっているの気づきました。ショートカット登録部分はiOS 13からビルトインになったショートカットAppに移動していました。
iPhone設定からなくなったことで、Appleの審査チームもアプリ内での「Siriに追加(Add to Siri)」ボタンを強く推奨しているのだろうと判断しました。

アプリ内に「Siriに追加(Add to Siri)」ボタンを付ける必要があるなあ。
ということで、審査中のバージョンを取り下げて、「Siriに追加(Add to Siri)」ボタンの実装を行うことにしました。

あらためて、iOS 13でのSiriの新機能や実装について調べました。

中旬

10日。起きたら右肘あたりに痛みがあり、右腕を動かしづらくなりました。
逆手懸垂をやったからかしらん、何年か前に鎖骨骨折してから少し運動がすぎると痛みが出て困るなあ、など思いました。
今回はなかなか治らず、まいりました。月末ぐらいに治りました。

iOS 13での「Siriに追加(Add to Siri)」ボタン機能追加は、短いコードを追加することでできる、はずだったのですが、うまくいかず。日本語表示されません。

INUIAddVoiceShortcutViewController displayed always in English

同じ問題で困っている人が、ひとり見つけたものの、回答がついてない。

なにか、やり方がまずいのかしらん。Siriの場合の言語指定のオプションがどこかにあるのかしら、と調べるもよくわからない。
あらためて、iOS 13でのSiriの新機能や実装について調べました。

Siri機能の実装についてWWDC 2019のビデオ見て、サンプルに触れました。

Soup Chef: Accelerating App Interactions with Shortcuts
Controlling Audio with SiriKit

最近のサンプルのモダンな書き方をなるほどなーと感心したり、MusicKitの扱いでdeveloper token作成の手順をややこしいと思いながらやったりしたものの、Siriのローカライズがうまくいかない問題は解決せず…

下旬

いまいち進みませんでした。

[iOS]動画を再生する(AVPlayerLayer使用)

(Xcode 11, Swift 5.1, iOS 13での実装)

iOSでの、動画を再生する機能の作成について前回に引き続いて記します。

AVPlayer – AVFoundation | Apple Developer Documentation

AVPlayerクラスを用いることで、映像やオーディオの再生ができます。
AVPlayerには画面に表示する機能がないので、前回はその部分をAVPLayerViewControllerがになう例を記しました。
今回は、AVPlayerLayerを使う例を記します。

AVPlayerLayer – AVFoundation | Apple Developer Documentation

AVPlayerLayerはplayerプロパティを持ち、そこにAVPlayerを渡すことで映像を表示できます。
実際に使う際には、このAVPlayerLayerのドキュメントに記されているプレイヤー用のUIViewサブクラスを用いる方法が扱いやすいです。

class PlayerView: UIView {
    var player: AVPlayer? {
        get {
            return playerLayer.player
        }
        set {
            playerLayer.player = newValue
        }
    }
    
    var playerLayer: AVPlayerLayer {
        return layer as! AVPlayerLayer
    }
    
    // Override UIView property
    override static var layerClass: AnyClass {
        return AVPlayerLayer.self
    }
}

Appleのドキュメントに乗っているコード例です。layerClassをオーバーライドしてこのUIViewがもつlayerはAVPlayerLayerクラスを返すようにしています。プロパティとしてplayerがあり、そこにAVPlayerをセットします。

この記事では、画面表示にこのPlayerViewを用いて、プロジェクトのリソースに加えた動画ファイルを再生する方法を記します。

動画を再生するサンプル

プロジェクトに追加してある動画ファイルを再生・一時停止するサンプルを作成します。バックグラウンドへ移行してもオーディオの再生・一時停止ができます。バックグラウンド移行時に動画再生中であった場合、一時停止するものを作成しますが、一時停止せずにオーディオを再生し続ける方法についても記します。全体のソースコードは記事の最後にまとめてあります。
ポイントになる箇所について、説明をおこないます。

動画再生機能作成については、Appleのドキュメントが参考になります。
Creating a Basic Video Player (iOS and tvOS) | Apple Developer Documentation

PlayerViewクラスを作成

今回は、ViewController.swiftのほかに、PlayerView.swiftを作成します。
File > New > File > Cocoa Touch Classから、UIViewをスーパークラスとするPlayerViewクラスを作成します。
内容は、前段に記したAppleのドキュメントに載っているPlayerViewコード例の通りです。記事の最後にも載せています。

動画ファイルをプロジェクトに加える

File > Add Files to <プロジェクト名>。
動画ファイルを選び、プロジェクトに加えます。
今回は、clip.mp4という名前の動画ファイルが加えられたとして話を進めます。

UI作成

Main.storyboard > View Controller。
UIViewとボタン二つを貼り付けます。
ボタンのテキストを「Play」「Pause」とします。
(画像ではUIViewのBackgroundはオレンジ色にしてありますが、これはどこに貼り付けたかを見やすくするためで、実際にはSystem Background Colorのままで構いません)

貼り付けたUIViewを選択し、Identity inspector > Custom Class > Classで、PlayerViewとします。

Player ViewとViewController.swiftをOutletで結び、名前をplayerViewとします。

一つのボタンのテキストを「Play」、もう一つのボタンのテキストを「Pause」とします。
PlayボタンとViewController.swiftをActionで結び、名前をplayBtnTappedとします。@IBAction func playBtnTapped(_ sender: Any) {}が生成されます。
PauseボタンとViewController.swiftをActionで結び、名前をpauseBtnTappedとします。@IBAction func pauseBtnTapped(_ sender: Any) {}が生成されます。

Audio Sessionの準備

AVAudioSession – AVFoundation | Apple Developer Documentation

Audio Sessionとはアプリがどのようにオーディオを扱うかを示すオブジェクトです。再生のみなのか、録音再生を行うのか、バックグラウンド再生ありにするのかなどを設定します。用意されたカテゴリ・モード・オプションから適切なものを選んで設定する形式になっています。
今回は、カテゴリをAVAudioSessionCategoryPlayback(オーディオ機能をメインとしたアプリ用カテゴリ。バックグラウンド再生可能)、モードをAVAudioSessionModeMoviePlayback(ムービー再生用)に設定します。

/// Audio sessionを動画再生向けのものに設定し、activeにします
let audioSession = AVAudioSession.sharedInstance()
do {
    try audioSession.setCategory(.playback, mode: .moviePlayback)
        
} catch {
    print("Setting category to AVAudioSessionCategoryPlayback failed.")
}

do {
    try audioSession.setActive(true)
    print("Audio session set active !!")
} catch {
    
}

バックグラウンド再生の準備

今回のサンプルでは、バックグラウンドでのオーディオ再生を行うので、その設定を行います。
TARGET > Signing & Capabilitiesを選択。
「+ Capability」ボタンから-> Background Modes

Audio, AirPlay and Picture in Pictureをチェック。

これにより、info.plistにRequired background modesが加わり、そのitemがApp plays audio or streams audio/video using AirPlayとなります。バックグラウンド再生が可能になります。

動画プレイヤー

urlからAVPlayerItemを作成します。
AVPlayerに作成したAVPlayerItemをセットします。
AVPlayerを動画表示を担当するAVPlayerLayerと結びつけます。
PlayerViewのプロパティであるplayerにAVPlayerをセットします。これによって、PlayerViewの動画表示をになうlayerと結びつけることができます。
今回は、ViewControllerクラスに追加したitemURLプロパティに動画のurlも渡しています。これは、あとで、NowPlayingInfo(現在再生中のアプリの状況)を表示するさいに使用します。

let fileName = "clip"
let fileExtension = "mp4"
guard let url = Bundle.main.url(forResource: fileName, withExtension: fileExtension) else {
    print("Url is nil")
    return
}

itemURL = url
let item = AVPlayerItem(url: url)
player = AVPlayer(playerItem: item)

playerView.player = player

リモートコントロール対応

イヤホンからの操作や、バックグラウンド移行後のコントロールセンターやロックスクリーンの再生コントロールからの操作に対応します。
MPRemoteCommandCenterクラスを用います。
また、コントロールセンターやロックスクリーンの再生コントロールに再生中アプリの現在の状況を表示する必要があります。それには、MPNowPlayingInfoCenterクラスを用います。
これらの実装については、Controlling Background Audio | Apple Developer Documentationが参考になります。

リモートコントロール対応部分

// MARK: Remote Command Event
func addRemoteCommandEvent() {
    
    let commandCenter = MPRemoteCommandCenter.shared()
    commandCenter.togglePlayPauseCommand.addTarget{ [unowned self] commandEvent -> MPRemoteCommandHandlerStatus in
        self.remoteTogglePlayPause(commandEvent)
        return MPRemoteCommandHandlerStatus.success
    }
    commandCenter.playCommand.addTarget{ [unowned self] commandEvent -> MPRemoteCommandHandlerStatus in
        self.remotePlay(commandEvent)
        return MPRemoteCommandHandlerStatus.success
    }
    commandCenter.pauseCommand.addTarget{ [unowned self] commandEvent -> MPRemoteCommandHandlerStatus in
        self.remotePause(commandEvent)
        return MPRemoteCommandHandlerStatus.success
    }
    commandCenter.nextTrackCommand.addTarget{ [unowned self] commandEvent -> MPRemoteCommandHandlerStatus in
        self.remoteNextTrack(commandEvent)
        return MPRemoteCommandHandlerStatus.success
    }
    commandCenter.previousTrackCommand.addTarget{ [unowned self] commandEvent -> MPRemoteCommandHandlerStatus in
        self.remotePrevTrack(commandEvent)
        return MPRemoteCommandHandlerStatus.success
    }
}

func remoteTogglePlayPause(_ event: MPRemoteCommandEvent) {
    // イヤホンのセンターボタンを押した時の処理
    // (略)
}

func remotePlay(_ event: MPRemoteCommandEvent) {
    // 再生ボタンが押された時の処理
    // (略)
}

func remotePause(_ event: MPRemoteCommandEvent) {
    // ポーズボタンが押された時の処理
    // (略)
}

func remoteNextTrack(_ event: MPRemoteCommandEvent) {
    // 「次へ」ボタンが押された時の処理
    // (略)
}

func remotePrevTrack(_ event: MPRemoteCommandEvent) {
    // 「前へ」ボタンが押された時の処理
    // (略)
}

NowPlayingInfo部分

この例では、動画ファイルのurlの末尾部分をタイトル表示に使用しています。
MPNowPlayingInfoCenterに示すことができるメタデータはほかにも様々なものがあります。
Now Playing Metadata Properties | MPNowPlayingInfoCenter – Media Player | Apple Developer Documentation

func setupNowPlaying(url: URL) {
    // Define Now Playing Info
    var nowPlayingInfo = [String : Any]()
    
    // ここでは、urlのlastPathComponentをtitleとして表示しています。
    nowPlayingInfo[MPNowPlayingInfoPropertyAssetURL] = url
    nowPlayingInfo[MPNowPlayingInfoPropertyMediaType] = MPNowPlayingInfoMediaType.video.rawValue
    nowPlayingInfo[MPNowPlayingInfoPropertyIsLiveStream] = false
    nowPlayingInfo[MPMediaItemPropertyTitle] = url.lastPathComponent
    nowPlayingInfo[MPMediaItemPropertyAlbumTitle] = ""
    
    // Set the metadata
    MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
}

バックグラウンド移行時の動作について

AVPlayerでは、動画再生中にバックグラウンドへ移行すると、一時停止するのがデフォルトの動作です。
もし、バックグラウンド移行時に再生しているオーディオを鳴らし続けたい場合は、追加の処理が必要になります。
これについては、Playing Audio from a Video Asset in the Background | Apple Developer Documentationのドキュメントに記されています。
バックグラウンド移行時にAVPlayerのインスタンスをplayerLayerから外す必要があります。

// フォアグラウンド移行時に呼び出されます
@objc func willEnterForeground(_ notification: Notification) {
    playerView.player = player
}
     
// バックグラウンド移行時に呼び出されます
@objc func didEnterBackground(_ notification: Notification) {
    playerView.player = nil
}

Playボタンを押すと動画が再生され、Pauseボタンを押すと動画が一時停止するサンプルを作成しました。イヤホン、コントロールセンターなどからの再生・一時停止もできます。

使用したソースコード

PlayerView.swift

import UIKit
import AVFoundation

class PlayerView: UIView {
    
    // The player assigned to this view, if any.
    
    var player: 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
    }
}

ViewController.swift

以下のソースコードでは、バックグラウンド移行時に一時停止する動作になっています。動画再生中のバックグラウンド移行のさいに、続けてオーディオ再生を行う場合は、willEnterForeground(_;)、didEnterBackground(_:)でのコメントアウトを外してください。

import UIKit
import AVFoundation
import MediaPlayer
import AVKit

class ViewController: UIViewController {

    @IBOutlet weak var playerView: PlayerView!
    
    var player = AVPlayer()
    var itemURL: URL?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        let audioSession = AVAudioSession.sharedInstance()
        do {
            try audioSession.setCategory(.playback, mode: .moviePlayback)
        } catch {
            print("Setting category to AVAudioSessionCategoryPlayback failed.")
        }
        do {
            try audioSession.setActive(true)
            print("audio session set active !!")
        } catch {
            
        }
        
        setupPlayer()
        
        addLifeCycleObserver()
        
        addRemoteCommandEvent()
    }
    
    private func setupPlayer() {
        let fileName = "clip"
        let fileExtension = "mp4"
        guard let url = Bundle.main.url(forResource: fileName, withExtension: fileExtension) else {
            print("Url is nil")
            return
        }
        
        itemURL = url
        let item = AVPlayerItem(url: url)
        player = AVPlayer(playerItem: item)
        
        playerView.player = player
        
    }

    /// Playボタンが押された
    @IBAction func playBtnTapped(_ sender: Any) {
        player.play()
        if let url = itemURL {
            setupNowPlaying(url: url)
        }
    }
        
    @IBAction func pauseBtnTapped(_ sender: Any) {
        player.pause()
    }
    
    // MARK: Life Cycle
    func addLifeCycleObserver() {
        let center = NotificationCenter.default
        center.addObserver(self, selector: #selector(willEnterForeground(_:)), name: UIApplication.willEnterForegroundNotification, object: nil)
        center.addObserver(self, selector: #selector(didEnterBackground(_:)), name: UIApplication.didEnterBackgroundNotification, object: nil)
    }
    
    // フォアグラウンド移行時に呼び出されます
    @objc func willEnterForeground(_ notification: Notification) {
        /// (動画再生中であったときにそのままオーディオ再生を続ける場合は、このあとのコメントアウトをとりのぞいてください)
        /// (バックグラウンド移行時に、playerLayerからplayerがはずされているので、再度つなげます。)
        //playerView.player = player
    }
         
    // バックグラウンド移行時に呼び出されます
    @objc func didEnterBackground(_ notification: Notification) {
        /// (動画再生中であったときにそのままオーディオ再生を続ける場合は、このあとのコメントアウトをとりのぞいてください)
        //playerView.player = nil
    }
    
    // MARK: Now Playing Info
    func setupNowPlaying(url: URL) {
        // Define Now Playing Info
        var nowPlayingInfo = [String : Any]()
        
        // ここでは、urlのlastPathComponentを表示しています。
        nowPlayingInfo[MPNowPlayingInfoPropertyAssetURL] = url
        nowPlayingInfo[MPNowPlayingInfoPropertyMediaType] = MPNowPlayingInfoMediaType.video.rawValue
        nowPlayingInfo[MPNowPlayingInfoPropertyIsLiveStream] = false
        nowPlayingInfo[MPMediaItemPropertyTitle] = url.lastPathComponent
        nowPlayingInfo[MPMediaItemPropertyAlbumTitle] = ""
        
        // Set the metadata
        MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
    }
    
    // MARK: Remote Command Event
    func addRemoteCommandEvent() {
        
        let commandCenter = MPRemoteCommandCenter.shared()
        commandCenter.togglePlayPauseCommand.addTarget{ [unowned self] commandEvent -> MPRemoteCommandHandlerStatus in
            self.remoteTogglePlayPause(commandEvent)
            return MPRemoteCommandHandlerStatus.success
        }
        commandCenter.playCommand.addTarget{ [unowned self] commandEvent -> MPRemoteCommandHandlerStatus in
            self.remotePlay(commandEvent)
            return MPRemoteCommandHandlerStatus.success
        }
        commandCenter.pauseCommand.addTarget{ [unowned self] commandEvent -> MPRemoteCommandHandlerStatus in
            self.remotePause(commandEvent)
            return MPRemoteCommandHandlerStatus.success
        }
        commandCenter.nextTrackCommand.addTarget{ [unowned self] commandEvent -> MPRemoteCommandHandlerStatus in
            self.remoteNextTrack(commandEvent)
            return MPRemoteCommandHandlerStatus.success
        }
        commandCenter.previousTrackCommand.addTarget{ [unowned self] commandEvent -> MPRemoteCommandHandlerStatus in
            self.remotePrevTrack(commandEvent)
            return MPRemoteCommandHandlerStatus.success
        }
    }
    
    func remoteTogglePlayPause(_ event: MPRemoteCommandEvent) {
        // イヤホンのセンターボタンを押した時の処理
        // (略)
    }
    
    func remotePlay(_ event: MPRemoteCommandEvent) {
        player.play()
    }
    
    func remotePause(_ event: MPRemoteCommandEvent) {
        player.pause()
    }

    func remoteNextTrack(_ event: MPRemoteCommandEvent) {
        // 「次へ」ボタンが押された時の処理
        // (略)
    }
    
    func remotePrevTrack(_ event: MPRemoteCommandEvent) {
        // 「前へ」ボタンが押された時の処理
        // (略)
        
    }

}

[iOS]動画を再生する(AVPlayerViewController使用)

(Xcode 11, Swift 5.1, iOS 13での実装)

iOSでの、動画を再生する機能の作成について記します。

AVPlayer – AVFoundation | Apple Developer Documentation

AVPlayerクラスを用いることで、映像やオーディオの再生ができます。
しかし、AVPlayerには画面に表示する機能はありません。
画面表示には、2つの方法があります。
 * AVPlayerViewControllerを使う。
 * AVPlayerLayerを使う。

AVPlayerViewControllerは、動画プレイヤー機能を簡単に作成できるクラスです。
iOS 8で追加され、iOSのアップデートごとに機能が拡充しています。
再生用のコントロールや、AirPlayサポート、Picture in Picture機能などが提供されます。

この記事では、画面表示にAVPlayerViewControllerを用いて、プロジェクトのリソースに加えた動画ファイルを再生する方法を記します。
(AVPlayerLayerを使った例はこちら

AVPlayerViewController – AVKit | Apple Developer Documentation

動画を再生するサンプル

動画再生機能作成については、Appleのドキュメントが参考になります。
Creating a Basic Video Player (iOS and tvOS) | Apple Developer Documentation

動画ファイルをプロジェクトに加える

File > Add Files to <プロジェクト名>。
動画ファイルを選び、プロジェクトに加えます。
今回は、clip.mp4という名前の動画ファイルが加えられたとして話を進めます。

UI作成

Main.storyboard > View Controllerにボタンを貼り付けます。
テキストを「Play Video」とします。

ボタンとViewControllerをActionで結び、NameをplayBtnTappedとします。@IBAction func playBtnTapped(_ sender: Any) {}が生成されます。

Audio Sessionの準備

AVAudioSession – AVFoundation | Apple Developer Documentation

Audio Sessionとはアプリがどのようにオーディオを扱うかを示すオブジェクトです。再生のみなのか、録音再生を行うのか、バックグラウンド再生ありにするのかなどを設定します。用意されたカテゴリ・モード・オプションから適切なものを選んで設定する形式になっています。
今回は、カテゴリをAVAudioSessionCategoryPlayback(オーディオ機能をメインとしたアプリ用カテゴリ。バックグラウンド再生可能)、モードをAVAudioSessionModeMoviePlayback(ムービー再生用)に設定します。

/// Audio sessionを動画再生向けのものに設定し、activeにします
let audioSession = AVAudioSession.sharedInstance()
do {
    try audioSession.setCategory(.playback, mode: .moviePlayback)
        
} catch {
    print("Setting category to AVAudioSessionCategoryPlayback failed.")
}

do {
    try audioSession.setActive(true)
    print("Audio session set active !!")
} catch {
    
}

バックグラウンド再生の準備

今回のサンプルでは、バックグラウンドでのオーディオ再生を行うので、その設定を行います。
TARGET > Signing & Capabilitiesを選択。
「+ Capability」ボタンから-> Background Modes

Audio, AirPlay and Picture in Pictureをチェック。

これにより、info.plistにRequired background modesが加わり、そのitemがApp plays audio or streams audio/video using AirPlayとなります。バックグラウンド再生が可能になります。

動画プレイヤー

AVPlayerにurlで指定された動画ファイルを渡します。
AVPlayerを動画の表示機能・再生コントロールを担当するAVPlayerViewControllerと結びつけます。
動画プレイヤーを再生します。

guard let url = Bundle.main.url(forResource: fileName, withExtension: fileExtension) else {
    print("Url is nil")
    return
}

// AVPlayerにアイテムをセット
let item = AVPlayerItem(url: url)
player.replaceCurrentItem(with: item)

// 動画プレイヤーにplayerをセット
playerController.player = player

// 動画プレイヤーを表示して再生
self.present(playerController, animated: true) {
    self.player.play()
}

以上で、「Play Video」ボタンを押すと、動画プレイヤーが起動し、動画が再生されます。再生コントロールが表示され、ポーズしたり再開したりできます。
画面下端からスワイプ(もしくはホームボタンを押す)ことで、バックグラウンドに移行すると、再生中の動画は一時停止します。コントロールセンターの再生コントロールから、再生を再開することができます。

使用したソースコード

ViewController.swift

import UIKit
import AVFoundation
import MediaPlayer
import AVKit

class ViewController: UIViewController {
 
    var playerController = AVPlayerViewController()
    var player = AVPlayer()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        /// Audio sessionを動画再生向けのものに設定し、activeにします
        let audioSession = AVAudioSession.sharedInstance()
        do {
            try audioSession.setCategory(.playback, mode: .moviePlayback)
                
        } catch {
            print("Setting category to AVAudioSessionCategoryPlayback failed.")
        }

        do {
            try audioSession.setActive(true)
            print("Audio session set active !!")
        } catch {
            
        }
        
    }

    /// 動画プレイヤーにアイテムをセットして更新
    private func playMovie(fileName: String, fileExtension: String) {
        guard let url = Bundle.main.url(forResource: fileName, withExtension: fileExtension) else {
            print("Url is nil")
            return
        }
        
        // AVPlayerにアイテムをセット
        let item = AVPlayerItem(url: url)
        player.replaceCurrentItem(with: item)
            
        // 動画プレイヤーにplayerをセット
        playerController.player = player
        
        // 動画プレイヤーを表示して再生
        self.present(playerController, animated: true) {
            self.player.play()
        }
    }
    
    /// Play Videoボタンが押されました
    @IBAction func playBtnTapped(_ sender: Any) {
        let fileName = "clip"
        let fileExtension = "mp4"
        playMovie(fileName: fileName, fileExtension: fileExtension)
    }
    
}

関連記事

[iOS]動画を再生する(AVPlayerLayer使用) – nackpan Blog

「Repete Plus」をアップデートしました。(version 7.2.3)

「Repete Plus」をアップデートしました。(version 7.2.2 -> version 7.2.3)

Repete Plusは、語学学習を支援するオーディオプレイヤーです。
無音部分を自動認識し、語学教材をフレーズごとに間隔をあけて再生できます。

App Storeはこちら

使い方を紹介しているサポートサイトはこちら
Repete Plus – nackpan Blog

変更点

  • イヤホンのボタンを押しても、オーディオのPlay/Pauseが行われない不具合を修正しました。

Xcode 11 + Swift 5.1になったさい(version 7.0)にリモートコマンドの書き方が変更になったのですが、そのさいの修正でバグを入れ込んでしまいました。イヤホンのボタンを押すコマンドであるtogglePlayPauseCommandを2回続けて、読み取るミスをおかしていました。申し訳ありません。修正しました。


語学学習を助ける「Repete Plus」をよろしくおねがいします。

「Repete」をアップデートしました(version 5.3)

iPhone/iPadアプリ「Repete」(レペテ)(旧「語学学習支援プレイヤー」)をアップデートしました。(version 5.1 -> version 5.3)

「Repete」(「語学学習支援プレイヤー」)は、語学学習の手助けをするオーディオプレイヤーです。ファイルの無音部分を分析し、流れる言葉が一区切りしたところで、あいだをおいて再生します
リピーティングに便利なオーディオプレイヤーです。

変更点

ダークモードに対応しました。

よろしくおねがいします

「Repete Plus」をアップデートしました。(version 7.2.2)

「Repete Plus」をアップデートしました。(version 7.2 -> version 7.2.2)

Repete Plusは、語学学習を支援するオーディオプレイヤーです。
無音部分を自動認識し、語学教材をフレーズごとに間隔をあけて再生できます。

App Storeはこちら

使い方を紹介しているサポートサイトはこちら
Repete Plus – nackpan Blog

変更点

  • iOS 13でイヤホンを抜くと強制終了する不具合がありました。申し訳ありません。
    このアップデートで修正しました。
  • 一部のラベルの文字色を適切なものに修正しました。

語学学習を助ける「Repete Plus」をよろしくおねがいします。