Logo
Overview

SwiftUIでPiPを使う話

July 26, 2025
1 min read

背景

PiPとはPicture in Pictureの略で、動画をスマホの画面にオーバーレイして表示するアレのことです。

YouTubeとかでよくありますよね。

あれをSwiftUIで実装しようとすると、ググった結果がよくわからないのでまとめてみました。

コード

やるべきポイントは三つです。そのどれが欠けてもPiPは動作しません。

AppDelegate

import AVFAudio
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
try? AVAudioSession.sharedInstance().setCategory(.playback, mode: .moviePlayback)
return true
}
}
@main
struct mainApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}

AppDelegateでこの設定を入れます。

VideoPlayerView

動画のURLが取得済みで、それを再生したい場合には以下のようなコードが利用できます。

URLはローカルでもリモートでも大丈夫です。

import AVKit
import SwiftUI
import Foundation
struct VideoPlayerView: UIViewControllerRepresentable {
let streamURL: URL
func makeUIViewController(context: Context) -> AVPlayerViewController {
let controller: AVPlayerViewController = .init()
let player: AVPlayer = .init(url: streamURL)
controller.player = player
controller.canStartPictureInPictureAutomaticallyFromInline = true
controller.player?.play()
return controller
}
func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) {
}
}

Capabilities

Targets > App > Signing & Capabilities > Background Modes > Audio, AirPlay and Picture in Piture

にチェックを入れます。

Implementing Picture-in-Picture in Swift for iOSの最初の方をそのまま実践するだけです。

まとめ

あとはVideoPlayerViewを適当なタイミングで呼び出します。

引数にstreamURLを持っているので、

struct TestView: View {
@State private var streamURL: URL?
var body: some View {
EmptyView()
.sheet(item: streamURL, content: { streamURL in
VideoPlayerView(streamURL: streamURL)
.ignoresSafeArea(.all)
})
}
}

みたいな感じで実装すればよいです。

記事は以上。