首页 > 其他分享 >swiftUI使用VideoPlayer和AVPlayer播放视频

swiftUI使用VideoPlayer和AVPlayer播放视频

时间:2024-06-02 18:28:35浏览次数:25  
标签:视频 mp4 self VideoPlayer player AVPlayer swiftUI https var

使用VideoPlayer包播放视频:https://github.com/wxxsw/VideoPlayer

提供一些可供测试的视频链接,不保证稳定可用哦:

https://vfx.mtime.cn/Video/2019/06/15/mp4/190615103827358781.mp4

https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4

https://vfx.mtime.cn/Video/2019/06/29/mp4/190629004821240734.mp4

https://vfx.mtime.cn/Video/2019/06/27/mp4/190627231412433967.mp4

https://vfx.mtime.cn/Video/2019/06/25/mp4/190625091024931282.mp4

https://vfx.mtime.cn/Video/2019/06/16/mp4/190616155507259516.mp4


https://vfx.mtime.cn/Video/2019/06/05/mp4/190605101703931259.mp4

安装VideoPlayer

使用spm安装包,直接在xcode项目的依赖包右键,添加包:

在右上角输入包地址:添加到项目中即可

使用VideoPlayer

在项目中导入:

import VideoPlayer

如果提示没有这个包:No such module 'VideoPlayer'

需要在项目的通用设置里面添加这个包到项目中:

选中 VideoPlayer 点击 add:

播放在线视频代码

直接使用在线视频url即可播放

    @State private var play: Bool = true

    var body: some View {
        VideoPlayer(url: URL(string: "你的视频URL链接")!, play: $play)
    }

实现的效果: 

播放本地视频

把视频添加到项目中,点击File > Add Files to 项目 > 选中要添加的视频,就可以了

然后在项目代码中添加视频:

// 本地文件
let localMp4Url = Bundle.main.url(forResource: "localMp4", withExtension: "mp4")


@State private var play: Bool = true


var body: some View {
    VideoPlayer(url: localMp4Url!, play: $play)
}

实现的效果:

视频控制

在视频上显示播放控制按钮等配置,可以通过给播放器绑定变量来实现控制

//
//  ContentView.swift
//  swiftPro
//
//  Created by song on 2024/5/21.
//

import Alamofire
import AVKit
import GIFImage
import Kingfisher
import SwiftUI
import VideoPlayer

private var videoURLs: [URL] = [
    URL(string: "https://vfx.mtime.cn/Video/2019/06/29/mp4/190629004821240734.mp4")!,
    URL(string: "https://vfx.mtime.cn/Video/2019/06/27/mp4/190627231412433967.mp4")!,
    URL(string: "https://vfx.mtime.cn/Video/2019/06/25/mp4/190625091024931282.mp4")!,
    URL(string: "https://vfx.mtime.cn/Video/2019/06/16/mp4/190616155507259516.mp4")!,
    URL(string: "https://vfx.mtime.cn/Video/2019/06/15/mp4/190615103827358781.mp4")!,
    URL(string: "https://vfx.mtime.cn/Video/2019/06/05/mp4/190605101703931259.mp4")!,
]

struct ContentView: View {
    // 本地文件
    let localMp4Url = Bundle.main.url(forResource: "localMp4", withExtension: "mp4")

    // 远程视频
    let remoteUrl = URL(string: "https://vfx.mtime.cn/Video/2019/06/15/mp4/190615103827358781.mp4")
    
    // 获取当前播放时间
    func getTimeString() -> String {
        let m = Int(time.seconds / 60)
        let s = Int(time.seconds.truncatingRemainder(dividingBy: 60))
        return String(format: "%d:%02d", arguments: [m, s])
    }
    
    // 获取视频所有的时间
    func getTotalDurationString() -> String {
        let m = Int(totalDuration / 60)
        let s = Int(totalDuration.truncatingRemainder(dividingBy: 60))
        return String(format: "%d:%02d", arguments: [m, s])
    }
    
    // 视频列表索引
    @State var index = 0
    // 播放状态
    @State private var play: Bool = true
    // 视频播放时间
    @State private var time: CMTime = .zero
    // 是否自动播放
    @State private var autoReplay: Bool = true
    // 是否开启声音(mute:沉默的,无声的)
    @State private var mute: Bool = false
    // 视频播放状态文字提示
    @State private var stateText: String = ""
    // 总共持续时间
    @State private var totalDuration: Double = 0
    // 播放速度
    @State private var speedRate: Float = 1.2

    // 使用状态来跟踪播放状态
    @State private var isPlaying = false

    var body: some View {
        VStack(content: {
            // 视频播放控制是通过绑定变量来实现的
            VideoPlayer(url: videoURLs[index % videoURLs.count], play: $play, time: $time)
                .autoReplay(autoReplay)
                .mute(mute)
                .speedRate(speedRate)
                .onBufferChanged { progress in print("onBufferChanged \(progress)") }
                .onPlayToEndTime { print("onPlayToEndTime") }
                .onReplay { print("onReplay") }
                .onStateChanged { state in
                    switch state {
                    case .loading:
                        self.stateText = "Loading..."
                    case .playing(let totalDuration):
                        self.stateText = "Playing!"
                        self.totalDuration = totalDuration
                    case .paused(let playProgress, let bufferProgress):
                        self.stateText = "Paused: play \(Int(playProgress * 100))% buffer \(Int(bufferProgress * 100))%"
                    case .error(let error):
                        self.stateText = "Error: \(error)"
                    }
                }
                .aspectRatio(1.78, contentMode: .fit)
                .cornerRadius(16)
                .shadow(color: Color.black.opacity(0.7), radius: 6, x: 0, y: 2)
                .padding()
            
            // 视频状态
            Text(stateText)
                .padding()
            
            // 视频控制:暂停/声音控制/自动重播/后退前进5秒/下一个视频
            HStack {
                Button(self.play ? "Pause" : "Play") {
                    self.play.toggle()
                }

                Divider().frame(height: 20)

                Button(self.mute ? "Sound Off" : "Sound On") {
                    self.mute.toggle()
                }

                Divider().frame(height: 20)

                Button(self.autoReplay ? "Auto Replay On" : "Auto Replay Off") {
                    self.autoReplay.toggle()
                }
            }

            HStack {
                Button("Backward 5s") {
                    self.time = CMTimeMakeWithSeconds(max(0, self.time.seconds - 5), preferredTimescale: self.time.timescale)
                }

                Divider().frame(height: 20)
                
                Text("\(getTimeString()) / \(getTotalDurationString())")

                Divider().frame(height: 20)

                Button("Forward 5s") {
                    self.time = CMTimeMakeWithSeconds(min(self.totalDuration, self.time.seconds + 5), preferredTimescale: self.time.timescale)
                }
            }

            Button("Next Video") { self.index += 1 }
            
        })
    }
}

#Preview {
    ContentView()
}

播放效果:

使用AVPlayer

导入AVPlayer:

import AVKit
import VideoPlayer

创建一个player:

注意视频链接协议要为https的,http的视频链接需要单独设置

    // 使用状态来跟踪播放状态
    @State private var isPlaying = false
    // AVPlayer 实例
    private let player = AVPlayer(url: URL(string: "https://vfx.mtime.cn/Video/2019/06/15/mp4/190615103827358781.mp4")!)



// 在ui层放入播放器
    var body: some View {
        VStack {
            // 视频播放器控件
            VideoPlayer(player: player)
                .ignoresSafeArea()
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .onAppear {
                    player.play()
                }
        }
    }

加载本地视频资源:

需要将本地视频资源加载到项目中,然后通过Bundle引入

    // 加载本地资源
    let player = AVPlayer(url: Bundle.main.url(forResource: "localMp4", withExtension: "mp4")!)

    var body: some View {
        VideoPlayer(player: player)
            .ignoresSafeArea()
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .onAppear {
                player.play()
            }
    }

 

显示效果:

播放也没有问题,视频控制也没有问题,很不错了

ipad的效果:果然是看剧神器,视觉效果还是不错的

可以添加自定义控制:

struct VideoPlayerView: View {
    // 使用状态来跟踪播放状态
    @State private var isPlaying = false
    // AVPlayer 实例
    private let player = AVPlayer(url: URL(string: "https://vfx.mtime.cn/Video/2019/06/15/mp4/190615103827358781.mp4")!)
 
    var body: some View {
        VStack {
            // 视频播放器控件
            AVPlayerViewController()
                .embed(player: player)
            // 添加自定义控制
            Button(action: togglePlay) {
                Text(isPlaying ? "暂停" : "播放")
            }
        }
    }
    
    // 切换播放状态的方法
    func togglePlay() {
        isPlaying ? player.pause() : player.play()
        isPlaying.toggle()
    }
}
 

extension AVPlayerViewController {
    func embed(player: AVPlayer) -> some View {
        return VideoPlayer(player: player)
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .edgesIgnoringSafeArea(.all)
            .onAppear {
                player.play()
            }
            .onDisappear {
                player.pause()
            }
    }
}

效果:

 

标签:视频,mp4,self,VideoPlayer,player,AVPlayer,swiftUI,https,var
From: https://blog.csdn.net/weixin_44786530/article/details/139186511

相关文章

  • SwiftUI中Popover的使用(弹出方式,箭头位置,如何退出)
    在iOS中,popover是出现在现有内容顶部的UI元素,通常用于在上下文中向用户呈现新视图。与其他占用整个屏幕的视图控制器不同,popover出现在一个较小的、集中的区域,从而使用户能够在必要时与popover外的应用程序的其他部分进行交互。这是一种有效的方式来显示额外的信息或选项,而......
  • SwiftUI中SafeArea的管理与使用(ignoresSafeArea, safeAreaPadding, safeAreaInset)
    SafeArea是指不与视图控制器提供的导航栏、选项卡栏、工具栏或其他视图重叠的内容空间。在UIKit中,开发人员需要使用safeAreaInsets或safeAreaLayoutGuide来确保视图被放置在界面的可见部分。SwiftUI彻底简化了上述过程,除非开发者明确要求视图突破安全区域的限制,否则SwiftU......
  • SwiftUI中AsyncImage的使用(一个高效的异步下载图片组件)
    iOS开发者经常会遇到需要在应用中显示网络图像的场景,无论是获取和显示用户头像,展示产品图像,等等。在原来的UIKit中,如果我们要用系统的API还是稍微有点麻烦,很多开发的朋友都选择了第三方的框架去处理网络图片的请求缓存等等。AsyncImage是SwiftUI中一个强大的功能,它简化了在......
  • SwiftUI中的组合动画(Simultaneous, Sequenced, Exclusive)
    了解了常见的几种手势后,接下来我们了解一下组合手势的操作,当一个视图存在多个手势的时候,为了避免手势冲突,SwiftUI提供了自定义手势的方法,比如同时进行,顺序进行等等。以下是一些常见的多种手势组合使用方式:simultaneously(with:):同时使用多个手势,使它们可以同时响应用户的......
  • SwiftUI中的手势(TapGesture、LongPressGesture、GestureState的使用)
    手势操作在App中可谓是用途非常广泛了,常规的手势修饰符有TapGesture点击手势、LongPressGesture长按手势、DragGesture拖拽手势,MagnificationGesture放缩手势和RoationGesture旋转手势。和常规的修饰符方法类似,只要将手势修饰符添加到视图中,系统就会自动识别用户的操作,并......
  • SwiftUI中的手势(DragGesture拖拽手势及Drag动画组件)
    上一篇文章我们了解了如何使用.gesture修饰符和@GestureState属性包装器,让我们看看另一种常见的手势:DragGesture拖拽手势。下面先看个效果图:这个效果中,我们实现了一个Text文本,并添加了拖拽手势,可以拖动到屏幕的任意位置,松手后停留在目标位置,而非回到原来的起点位置。UI......
  • SwiftUI State,Binding 状态管理
    代码////ContentView.swift//SwiftUIState////CreatedbyCHENHaoon2024/5/8.//importSwiftUIstructContentView:View{@StateprivatevarisPlaying=false@StateprivatevarclickNumber1=0@StateprivatevarclickNumber2=0......
  • DevTutor 一款旨在帮助开发者使用 SwiftUI 创建出色应用程序的应用
    提供可复制的代码示例和相应的用户界面预览,以简化您的编码过程。此外,还包括了《Swift编程语言》官方中英文文档的本地离线预览。主要功能■提供可直接在您的项目中使用的样本代码■实时查看您的代码如何影响应用的外观■提供官方中英文Swift编程语言离线文档■探索第......
  • SwiftUI ScrollView 滚动视图
    代码////ContentView.swift//SwiftUIScrollView////CreatedbyCHENHaoon2024/5/7.//importSwiftUIstructContentView:View{varbody:someView{VStack(alignment:.leading){VStack(alignment:.leading){......
  • SwiftUI ZStack、HStack、VStack 布局
    代码////ContentView.swift//SwiftUIStacks////CreatedbyCHENHaoon2024/5/6.//importSwiftUIstructContentView:View{varbody:someView{VStack(spacing:15){HeaderView()HStack(spacing:15){......