swiftUI使用VideoPlayer和AVPlayer播放视频

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

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

https://vfx.mtime.cn/Video/2019/06/15/mp4/190615103827358781.mp4https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4https://vfx.mtime.cn/Video/2019/06/29/mp4/190629004821240734.mp4https://vfx.mtime.cn/Video/2019/06/27/mp4/190627231412433967.mp4https://vfx.mtime.cn/Video/2019/06/25/mp4/190625091024931282.mp4https://vfx.mtime.cn/Video/2019/06/16/mp4/190616155507259516.mp4https://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 = truevar 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 = truevar 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 VideoPlayerprivate 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 = falsevar 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 inswitch state {case .loading:self.stateText = "Loading..."case .playing(let totalDuration):self.stateText = "Playing!"self.totalDuration = totalDurationcase .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()}}
}

效果:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/343060.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ES 8的向量检索性能调优实践

前言 ES的官方实验室曾发布过一篇博客,介绍了使ES向量检索性能获得显著提升的技术要点与展望: 多线程搜索能力的利用:Lucene 的分段架构允许实现多线程搜索能力。Elasticsearch 通过同时搜索多个段来提高性能,使用所有可用的 CPU 核心的计算能力显著减少了单个搜索的延迟。…

【全开源】CMS内容管理系统(ThinkPHP+FastAdmin)

基于ThinkPHPFastAdmin的CMS内容管理系统,自定义内容模型、自定义单页、自定义表单、专题、统计报表、会员发布等 提供全部前后台无加密源代码和数据库私有化部署,UniAPP版本提供全部无加密UniAPP源码​ 🔍 解锁内容管理新境界:C…

巧用Jmeter Debug sampler获取变量信息

Jmeter Debug sampler介绍 Jmeter Debug sampler 可以帮助我们解决如下问题: debug参数化的变量取值是否正确 debug正则表达式提取器(或json提取器)提取的值是否正确 查看 JMeter 属性 具体使用方法 前提条件:添加查看结果树…

【机器学习】机器学习与智能交通在智慧城市中的融合应用与性能优化新探索

文章目录 引言机器学习与智能交通的基本概念机器学习概述监督学习无监督学习强化学习 智能交通概述交通流量预测交通拥堵管理智能信号控制智能停车管理 机器学习与智能交通的融合应用实时交通数据分析数据预处理特征工程 交通流量预测与优化模型训练模型评估 智能信号控制与优化…

运维监控领域你不得不知道的黑话-下篇

作者:Tshb 引言 书接上回:《运维监控领域你不得不知道的黑话-中篇》。 在上一讲中,我们对监控系统中的四种指标类型进行了详细的阐述。不同类型的指标可以提供不同维度的系统信息,通过对比不同类型的指标,可以让我们…

软硬件集成项目,这个项目管理软件做的成本预算管理深得我心

最近,我负责了一个中大型的软硬件集成的项目,是对某单位的车间进行智能化改造,以提高生产效率,要确保设备运行的稳定性和安全性。项目会涉及到大量的硬件采购、安装以及多个软件的开发、集成,所以在实施过程中遇到了多…

vue 如何制作一个跟随窗口大小变化而变化的组件

vue 如何制作一个跟随窗口大小变化而变化的组件 像下图中展示的那些统计数件就是跟随窗口变化而变化的,而且是几乎等比缩放的。 实现原理 只简略说一下原理。 pinia 中记录一个窗口变化的高度值给要变化的组件添加一个高度值组件内部所有关于长度距离的值都通过这…

(uniapp)简单带动画的tab切换效果

效果图 代码 <template><view class"tabBox"><view :style"{transform: translateX(${translateX})}" class"whiteBox"></view><view click"changeTab(k)" class"itemBox" v-for"(v,k) in…

分享一个 .Net core Console 项目使用 SqlSugar 的详细例子

前言 SqlSugar 是一款老牌的 .NET 开源 ORM 框架&#xff0c;性能高&#xff0c;功能全面&#xff0c;使用简单&#xff0c;支持 .NET FrameWork、.NET Core3.1、.NET5、.NET6、.NET7、.NET8、.NET9 等版本&#xff0c;线上论坛非常活跃&#xff0c;今天给大伙分享一个 .Net c…

Web3的应用场景分析

Web3&#xff0c;即基于区块链技术的去中心化互联网&#xff0c;正逐渐改变我们与数字世界的互动方式。以下是Web3的一些主要应用场景。Web3技术正在各个领域推动创新&#xff0c;创造更多透明、开放和去中心化的解决方案&#xff0c;为用户带来更高的自主权和安全性。北京木奇…

【全开源】同城招聘SAAS信息前程无忧直聘达小程序

招聘SAAS&#xff1a;数字化转型中的招聘新助力 基于ThinkPHP和原生微信小程序开发的招聘平台系统&#xff0c;包含微信小程序求职者端、微信小程序企业招聘端、PC企业招聘端、PC管理平台端​ &#x1f31f; 一、招聘SAAS简介 在人力资源领域&#xff0c;数字化转型已成为不…

工会考试基础知识题库分享(附答案解析)

单选题 1、国家机关在组织起草或者修改直接涉及职工切身利益的法律、法规、规章时&#xff0c;( )工会意见。 A、可以听取 B、应当听取 C、必须听取 D、应当吸收 [答案]B 【解析】国家机关在组织起草或者修改直接涉及职工自身利益的法律、法规、规章时&#xff0c;应当听取工…

如何查询公网IP?

在互联网中&#xff0c;每个设备都有一个唯一的公网IP地址&#xff0c;用于标识设备在全球范围内的位置。查询公网IP是一个常见的需求&#xff0c;无论是用于远程访问、网络配置还是其他目的&#xff0c;了解自己的公网IP地址都是很有必要的。本文将介绍几种常见的方法来查询公…

面向AI应用开发实战分享 - 基础篇

“前端转AI&#xff0c;第一讲来了” 引言 如果你是一名前端开发&#xff0c;同时又对AI开发很感兴趣&#xff0c;那么恭喜你&#xff0c;机会来了。 如果不是也没关系&#xff0c;同样能帮大家了解AI应用的开发思路。 本文将带大家从面向AI开发的基础知识开始&#xff0c;再…

攻防实战 | 邮件高级威胁检测与自动化响应

历经三个月的时间&#xff0c;年度重磅直播节目Fortinet 2024年度“Demo季”近日终于迎来了备受瞩目的压轴大戏——Demo Day第三期&#xff0c;主题为《新邮件安全下的高级威胁检测与自动化响应》。继成功举办了前两期《企业网络中的多源威胁情报自动化整合与集成》和《应急响应…

人工智能绘画的历史

人工智能绘画的起源可以追溯到20世纪50年代。当时&#xff0c;艺术家和科学家开始使用计算机生成图像和图形&#xff0c;将绘画艺术与技术领域相结合。计算机图像可以被视为人工智能绘画的一部分。下面&#xff0c;我们将按照时间顺序来了解人工智能绘画发展的一些关键时间节点…

代码审计(1):CVE-2022-4957分析及复现

0x00漏洞描述&#xff1a; ѕрееdtеѕt iѕ а vеrу liɡhtԝеiɡ&#xff48;t nеtԝоrk ѕрееd tеѕtinɡ tооl imрlеmеntеd in Jаvаѕсriрt. Thеrе iѕ а Crоѕѕ-ѕitе Sсriрtinɡ vulnеrаbilitу in librеѕроndеd ѕрееdtеѕt…

JeeSite 快速开发平台 Vue3 前端版介绍

JeeSite 快速开发平台 Vue3 前端版介绍&#xff1a; 它构建于 Vue3、Vite、Ant-Design-Vue、TypeScript 以及 Vue Vben Admin 等最前沿的技术栈之上&#xff0c;能助力初学者迅速上手并顺利融入团队开发进程。涵盖的模块包括组织机构、角色用户、菜单授权、数据权限、系统参数…

小牛翻译API详解:功能、优势介绍及案例实战(附完整代码)

写在前面小牛翻译是做什么的案例-调用图片翻译API进行英文翻译✔准备工作✔获取密钥✔调用API✔完整代码✔运行项目 使用建议 写在前面 随着全球化的快速发展和跨国交流的增多&#xff0c;翻译软件的市场需求持续增长。根据市场数据&#xff0c;全球语言翻译软件市场规模在过去…

Linux命令篇(六):vi/vim专项

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝您生活愉快&#xff01; 文章目录 一、什么是vim二…