Brightcove 在以下 iOS 版本的最新公开版本上提供对最新 iOS SDK 的主动支持:
Brightcove 为以下 iOS 版本提供被动支持:
核心 SDK 已本地化为阿拉伯语 (ar)、英语 (en)、法语 (fr)、德语 (de)、日语 (ja)、韩语 (ko)、西班牙语 (es)、简体中文 (zh-Hans) 和繁体中文中文(zh-Hant)。为了获得本地化的好处,您的应用程序还必须针对相同的语言和区域设置进行本地化。有关更多信息,请参阅自定义本地化部分。
所有 SDK 组件(核心框架和插件框架)均以相同的版本号发布。升级任何单个组件时,请将所有组件升级到同一版本。
对于在 Apple Silicon M1 和通用框架 (.framework) 上使用 Xcode 12 的项目,在为 arm64 模拟器构建项目时会返回构建错误。
*ld: building for iOS Simulator, but linking in dylib built for iOS, file for architecture arm64*
要构建arm64模拟器,请确保arm64
已添加到应用程序目标的“构建设置”选项卡中Any iOS Simulator SDK
的“排除架构”构建设置中。
Brightcove Player SDK 6.10.0 版添加了核心子规范和每个插件以支持 XCFrameworks。每个子规范的默认值为/XCFramework
。
Podspec 名称 | 亚种名称 |
---|---|
Brightcove-玩家核心 | Brightcove-播放器-核心/框架 Brightcove-Player-Core/XCFramework |
Brightcove-玩家-DAI | Brightcove-播放器-DAI/框架 Brightcove-播放器-DAI/XCFramework |
Brightcove-Player-FreeWheel | Brightcove-玩家自由轮/框架 Brightcove-Player-FreeWheel/XCFramework |
Brightcove-播放器-GoogleCast | Brightcove-播放器-GoogleCast/框架 Brightcove-播放器-GoogleCast/XCFramework |
Brightcove-播放器-IMA | Brightcove-播放器-IMA/框架 Brightcove-播放器-IMA/XCFramework |
Brightcove-玩家-Omniture | Brightcove-播放器-Omniture/框架 Brightcove-Player-Omniture/XCFramework |
Brightcove-玩家脉动 | Brightcove-玩家脉冲/框架 Brightcove-玩家-Pulse/XCFramework |
Brightcove-播放器-SSAI | Brightcove-播放器-SSAI/框架 Brightcove-播放器-SSAI/XCFramework |
Brightcove-播放器-OpenMeasurement | - |
Brightcove Player SDK 版本 6.12.0 更新了Brightcove-Player-FreeWheel
和Brightcove-Player-Omniture
podspec 以安装动态版本的BrightcovePlayerSDK
。
Podspec 名称 | 框架类型 | 依赖性 |
---|---|---|
Brightcove-玩家核心 | 动态的 | - |
Brightcove-Player-DAI(自 6.12.7 起可用) | 动态的 | Brightcove-玩家核心 |
Brightcove-Player-FreeWheel | 动态的 | iOS 版 Brightcove-Player-Core, 适用于 tvOS 的 Brightcove-Player-Core |
Brightcove-播放器-GoogleCast | 静止的 | Brightcove-玩家核心 |
Brightcove-播放器-IMA | 动态的 | Brightcove-玩家核心 |
Brightcove-玩家-Omniture | 动态的 | Brightcove-玩家核心 |
Brightcove-玩家脉冲 | 动态的 | Brightcove-玩家核心 |
Brightcove-播放器-SSAI | 动态的 | Brightcove-玩家核心, Brightcove-Player-OpenMeasurement(仅适用于开放测量) |
Brightcove-Player-OpenMeasurement(自 6.10.0 起可用) | 动态的 | - |
对受 FairPlay 保护的视频的支持已集成到核心BrightcovePlayerSDK框架中。有关将 FairPlay 与 Brightcove Native Player SDK 结合使用的完整详细信息,请参阅 FairPlay 指南。
对 Sidecar 字幕的支持已集成到核心BrightcovePlayerSDK框架中。有关将 Sidecar Subtitles 与 Brightcove Native Player SDK 结合使用的完整详细信息,请参阅 Sidecar Subtitles 指南。
自版本 6.0.0 起,Brightcove Native Player SDK 允许您下载 HLS 视频,包括受 FairPlay 加密保护的视频,以便稍后在线或离线播放。有关完整详细信息,请参阅应用程序开发人员指南:
iOS 应用程序开发人员使用 FairPlay 进行视频下载和离线播放的指南
Brightcove Player SDK 提供 iOS 和 tvOS 的安装包,作为打包为 Frameworks 和 XCFrameworks 的动态库。 iOS 12.0 及更高版本支持部署。
您可以使用 CocoaPods 将 Brightcove Player SDK 添加到您的项目中。您可以在此处找到最新的Brightcove-Player-Core
podspec。 podspec 同时支持 iOS 和 tvOS。
在项目中使用 Brightcove CocoaPods 时,请将source 'https://github.com/brightcove/BrightcoveSpecs.git'
添加到 Podfile 的开头。
姓名。
source ' https://github.com/CocoaPods/Specs '
source ' https://github.com/brightcove/BrightcoveSpecs.git '
platform :ios, ' 12.0 '
use_frameworks !
target ' MyVideoPlayer ' do
pod ' Brightcove-Player-Core '
end
可以通过将/Framework
规范附加到 pod 来安装框架。
source ' https://github.com/CocoaPods/Specs '
source ' https://github.com/brightcove/BrightcoveSpecs.git '
platform :ios, ' 12.0 '
use_frameworks !
target ' MyVideoPlayer ' do
pod ' Brightcove-Player-Core/Framework '
end
更新安装时,最好刷新 BrightcoveSpecs 存储库的本地副本,以便您在本地拥有最新的 podspec,就像更新 CococaPods 主存储库一样。通常,如果您在终端中运行pod update
这将自动发生,或者您可以使用pod repo update
显式更新。
要将 Brightcove Player SDK 手动添加到您的项目中:
BrightcovePlayerSDK.framework
或BrightcovePlayerSDK.xcframework
添加到您的项目中。请务必使用与您的目标、iOS 或 tvOS 相对应的版本。BrightcovePlayerSDK.framework
/ BrightcovePlayerSDK.xcframework
bash ${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/BrightcovePlayerSDK.framework/strip-frameworks.sh
添加“运行脚本”阶段。选中“仅在安装时运行脚本”。这将从构建中删除不需要的架构,这对于 App Store 提交非常重要。使用 XCFramework 时不再需要此步骤。bash ${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/BrightcovePlayerSDK.framework/strip-frameworks.sh
添加“运行脚本”阶段。选中“仅在安装时运行脚本”。这将从构建中删除不需要的架构,这对于 App Store 提交非常重要。arm64
已添加到Any iOS Simulator SDK
的“排除架构”构建设置中。作为参考,以下是所有 SDK 组件和相应的 URL,可帮助您查找和下载最新版本:
成分 | 网址 |
---|---|
Brightcove-玩家核心 | https://github.com/brightcove/brightcove-player-sdk-ios/tags |
Brightcove-玩家-DAI | https://github.com/brightcove/brightcove-player-sdk-ios-dai/tags |
Brightcove-Player-FreeWheel | https://github.com/brightcove/brightcove-player-sdk-ios-fw/tags |
Brightcove-播放器-GoogleCast | https://github.com/brightcove/brightcove-player-sdk-ios-googlecast/tags |
Brightcove-播放器-IMA | https://github.com/brightcove/brightcove-player-sdk-ios-ima/tags |
Brightcove-玩家-Omniture | https://github.com/brightcove/brightcove-player-sdk-ios-omniture/tags |
Brightcove-玩家脉冲 | https://github.com/brightcove/brightcove-player-sdk-ios-pulse/tags |
Brightcove-播放器-SSAI | https://github.com/brightcove/brightcove-player-sdk-ios-ssai/tags |
要使用 Swift Package Manager 将 Brightcove Player SDK 添加到您的项目中:
https://github.com/brightcove/brightcove-player-sdk-ios.git
注意:Swift Package Manager 仅支持动态 XCFramework。
适用于 iOS 的 Brightcove Player SDK 可以使用以下方式导入:
import BrightcovePlayerSDK;
使用适用于 iOS 的 Brightcove Player SDK 播放视频:
// ** Customize these values with your own account information **
let kAccountId = " ... "
let kPolicyKey = " ... "
let kVideoId = " ... "
let sdkManager = BCOVPlayerSDKManager . sharedManager ( )
let playbackController = sdkManager . createPlaybackController ( )
self . playbackController = playbackController // store this to a strong property
view . addSubview ( playbackController . view )
let playbackService = BCOVPlaybackService ( withAccountId : kAccountId ,
policyKey : kPolicyKey )
let configuration = [
BCOVPlaybackService . ConfigurationKeyAssetID : kVideoId
]
playbackService . findVideo ( withConfiguration : configuration ,
queryParameters : nil ) { ( video : BCOVVideo ? ,
jsonResponse : Any ? ,
error : Error ? ) in
if let video {
self . playbackController ? . setVideos ( [ video ] )
self . playbackController ? . play ( )
}
}
您需要防止控制器在方法结束时自动释放。执行此操作的常见方法是将控制器的引用存储在强实例变量中。
从5.1.0版本开始,Brightcove PlayerUI完全集成到Core SDK框架中。 PlayerUI 提供了一套功能齐全的播放和广告控件,开箱即用。
PlayerUI 可以快速设置,显示 SSAI、Pulse 和 FreeWheel 的广告控件,并且可以通过创建自己的布局进行自定义。
请遵循以下指南来设置 PlayerUI 控件。
在 UIViewController 中创建一个属性来跟踪 BCOVPUIPlayerView。 BCOVPUIPlayerView 将包含播放控制器的视图和控件视图。
// PlayerUI's Player View
var playerView : BCOVPUIPlayerView ?
创建 BCOVPUIBasicControlView,然后创建 BCOVPUIBasicControlView。这是我们将播放控制器(以及它播放的所有视频)与控件关联起来的地方。
// Create and configure Control View.
let controlView = BCOVPUIBasicControlView . withVODLayout ( )
playerView = BCOVPUIPlayerView ( playbackController : self . playbackController , options : nil )
// Add BCOVPUIPlayerView to your video view.
if let playerView {
videoView . addSubview ( playerView )
}
您需要设置播放器视图的布局,可以使用自动布局或旧的 Springs & Struts 方法来完成此操作。
设置播放器视图,使其在调整大小时与布局 ( videoView
) 中的视频容器相匹配。
playerView . frame = videoView . bounds
playerView . autoresizingMask = [ . flexibleHeight , . flexibleWidth ]
将 BCOVPUIPlayerView 上的translatesAutoresizingMaskIntoConstraints
设置为false
。
playerView . translatesAutoresizingMaskIntoConstraints = false
然后添加布局的约束;将 BCOVPUIPlayerView 的顶部、右侧、左侧和底部锚点设置为等于videoView
的锚点
NSLayoutConstraint . activate ( [
playerView . topAnchor . constraint ( equalTo : videoView . topAnchor ) ,
playerView . rightAnchor . constraint ( equalTo : videoView . rightAnchor ) ,
playerView . bottomAnchor . constraint ( equalTo : videoView . bottomAnchor ) ,
playerView . leftAnchor . constraint ( equalTo : videoView . leftAnchor )
] )
BCOVPUIPlayerViewOptions
类允许您在初始化时自定义一些 BCOVPlayerUI 行为。您可以自定义以下内容:
jumpBackInterval
按下跳回按钮时播放器将向后查找的时间(以秒为单位)。
hideControlsInterval
最后一次触摸事件之后、隐藏控件之前的时间(以秒为单位)。
hideControlsAnimationDuration
控件以动画方式隐藏所需的时间(以秒为单位)。
showControlsAnimationDuration
控件动画显示所需的时间(以秒为单位)。
learnMoreButtonBrowserStyle
用于确定点击广告上的“了解更多”按钮是否会在外部浏览器(默认设置)或内部浏览器中显示点击链接的设置。
presentingViewController
用于呈现其他视图控制器(如隐藏式字幕选择视图控制器)的 UIViewController 子类。
automaticControlTypeSelection
是否希望BCOVPUIPlayerView
根据媒体类型自动选择BCOVPUIBasicControlView
类型。当此值设置为true
时,传递到BCOVPUIBasicControlView
初始值设定项的BCOVPUIPlayerView
属性将被忽略。
视频+音频流
basicControlViewWithVODLayout
basicControlViewWithLiveLayout
basicControlViewWithLiveDVRLayout
纯音频流
basicControlViewWithAODLayout
basicControlViewWithLiveAudioLayout
basicControlViewWithLiveDVRAudioLayout
注意: automaticControlTypeSelection
从 BCOVPlayerUI 提供的布局中选择布局,因此自定义控件和布局将被覆盖; automaticControlTypeSelection
和播放器 UI 自定义不兼容。
可以使用以下方法设置选项:
let manager = BCOVPlayerSDKManager . sharedManager ( )
let playbackController = manager . createPlaybackController ( )
let options = BCOVPUIPlayerViewOptions ( )
options . jumpBackInterval = 5
let playerView = BCOVPUIPlayerView ( playbackController : playbackController ,
options : options )
提供三种布局来支持不同类型的视频:
BCOVPUIControlLayout basicVODControlLayout
是一般点播视频流的基本布局。
BCOVPUIControlLayout basicLiveControlLayout
是直播视频的布局。
BCOVPUIControlLayout basicLiveDVRControlLayout
是带有 DVR 控件的实时视频流的布局。
您通常在创建BCOVPUIPlayerView
后立即设置新布局,但也可以随时设置新布局。例如,您可以像这样设置新的 VOD 布局:
playerView ? . controlsView . layout = BCOVPUIControlLayout . basicVOD ( )
除了默认布局之外,您还可以通过使用自己的设计实例化新的BCOVPUIControlLayout
来创建自己的高度自定义布局。但请注意, automaticControlTypeSelection
从 BCOVPlayerUI 提供的布局中选择布局,因此自定义控件和布局将被覆盖; automaticControlTypeSelection
和播放器 UI 自定义不兼容。
首先,使用BCOVPUIBasicControlView layoutViewWithControlFromTag:width:elasticity:
创建将进入布局的控件。每个控件都封装在BCOVPUILayoutView
中,该视图确定控件间距。
您可以将每个布局视图的width
设置为默认宽度(基于控件的类型),也可以指定您自己的宽度。
使用elasticity
参数来确定包含控件的布局视图调整其宽度以填充控制栏的程度。
以下是创建各种基本控件的示例。
// Create various standard layout views
// Standard play/pause button
let playbackLayoutView = BCOVPUIBasicControlView . layoutViewWithControl ( from : BCOVPUIViewTag . buttonPlayback ,
width : kBCOVPUILayoutUseDefaultValue ,
elasticity : 0.0 )
// Standard jump back button
let jumpBackButtonLayoutView = BCOVPUIBasicControlView . layoutViewWithControl ( from : BCOVPUIViewTag . buttonJumpBack ,
width : kBCOVPUILayoutUseDefaultValue ,
elasticity : 0.0 )
// Current time indicator
let currentTimeLayoutView = BCOVPUIBasicControlView . layoutViewWithControl ( from : BCOVPUIViewTag . labelCurrentTime ,
width : kBCOVPUILayoutUseDefaultValue
elasticity : 0.0 )
// Time separator - typically the '/' character
let timeSeparatorLayoutView = BCOVPUIBasicControlView . layoutViewWithControl ( from : BCOVPUIViewTag . labelTimeSeparator ,
width : kBCOVPUILayoutUseDefaultValue ,
elasticity : 0.0 )
// Video duration label
let durationLayoutView = BCOVPUIBasicControlView . layoutViewWithControl ( from : BCOVPUIViewTag . labelDuration ,
width : kBCOVPUILayoutUseDefaultValue ,
elasticity : 0.0 )
// Slider bar used for seeking through the video
// The elasticity is set to 1 so that it can resize to fill available space
let progressLayoutView = BCOVPUIBasicControlView . layoutViewWithControl ( from : BCOVPUIViewTag . sliderProgress ,
width : kBCOVPUILayoutUseDefaultValue ,
elasticity : 1.0 )
// Closed caption button
// This button is initially hidden ('removed'), and will be shown
// if closed captions or audio tracks are available.
let closedCaptionLayoutView = BCOVPUIBasicControlView . layoutViewWithControl ( from : BCOVPUIViewTag . buttonClosedCaption ,
width : kBCOVPUILayoutUseDefaultValue ,
elasticity : 0.0 )
closedCaptionLayoutView ? . isRemoved = true
// The full-screen button
let screenModeLayoutView = BCOVPUIBasicControlView . layoutViewWithControl ( from : BCOVPUIViewTag . buttonScreenMode ,
width : kBCOVPUILayoutUseDefaultValue ,
elasticity : 0.0 )
// AirPlay button
// This button is initially hidden ('removed'), and will be shown
// if AirPlay devices are available.
let externalRouteLayoutView = BCOVPUIBasicControlView . layoutViewWithControl ( from : BCOVPUIViewTag . viewExternalRoute ,
width : kBCOVPUILayoutUseDefaultValue ,
elasticity : 0.0 )
externalRouteLayoutView ? . isRemoved = true
// Empty view - used as a spacer
let spacerLayoutView1 = BCOVPUIBasicControlView . layoutViewWithControl ( from : BCOVPUIViewTag . viewEmpty ,
width : 1.0 ,
elasticity : 1.0 )
// Empty view - used as a spacer
let spacerLayoutView2 = BCOVPUIBasicControlView . layoutViewWithControl ( from : BCOVPUIViewTag . viewEmpty ,
width : 1.0 ,
elasticity : 1.0 )
// Empty view - will have a custom UIImageView added as a subview
let logoLayoutView1 = BCOVPUIBasicControlView . layoutViewWithControl ( from : BCOVPUIViewTag . viewEmpty ,
width : 88.0 ,
elasticity : 1.0 )
// Empty view - will have a custom UIImageView added as a subview
let logoLayoutView2 = BCOVPUIBasicControlView . layoutViewWithControl ( from : BCOVPUIViewTag . viewEmpty ,
width : 36.0 ,
elasticity : 1.0 )
请注意,您还可以创建一个空布局视图,在其中可以放置您自己的视图(徽标、控件、无内容等)。此代码展示了如何将UIImage
徽标放置在我们上面创建的 logoLayoutView1 中。
// Create logo image inside an image view for display in control bar.
let logoImage1 = UIImage ( named : " myLogo " )
let logoImageView1 = UIImageView ( image : logoImage1 )
logoImageView1 . autoresizingMask = [ . flexibleWidth , . flexibleHeight ]
logoImageView1 . contentMode = . scaleAspectFit
logoImageView1 . frame = logoLayoutView1 . frame
// Add image view to our empty layout view.
logoLayoutView1 . addSubview ( logoImageView1 )
现在布局视图中封装了各种控件,它们被排序成数组,每个数组代表一行控件,即一个控件栏。请注意,纵向和横向可以有不同的布局,因此您通常会设置两个不同的控制栏阵列。
在横向的标准布局中,控件排列在单个数组中,然后该数组存储在表示整个控件集的另一个数组中。
let standardLayoutLine1 = [
playbackLayoutView ,
jumpBackButtonLayoutView ,
currentTimeLayoutView ,
timeSeparatorLayoutView ,
durationLayoutView ,
progressLayoutView ,
spacerLayoutView1 ,
logoLayoutView1 ,
spacerLayoutView2 ,
closedCaptionLayoutView ,
screenModeLayoutView ,
externalRouteLayoutView
]
let standardLayoutLines = [ standardLayoutLine1 ]
在纵向的紧凑布局中,创建了两个控件数组,每一行一个。这些数组被打包到另一个表示紧凑布局的数组中。
请注意,每个布局中的大多数控件都使用完全相同的对象。完成此操作后,当您在纵向和横向方向之间切换时,对象将使用平滑的动画移动到新位置。
let compactLayoutLine1 = [
currentTimeLayoutView ,
progressLayoutView ,
durationLayoutView
]
let compactLayoutLine2 = [
playbackLayoutView ,
jumpBackButtonLayoutView ,
spacerLayoutView1 ,
closedCaptionLayoutView ,
screenModeLayoutView ,
externalRouteLayoutView ,
logoLayoutView2
]
let compactLayoutLines = [
compactLayoutLine1 ,
compactLayoutLine2
]
最后,现在有两种布局配置(一种用于全宽度,一种用于紧凑宽度),您可以创建一个新的BCOVPUIControlLayout
对象,并将其设置在播放器的控制视图中。
let customLayout = BCOVPUIControlLayout . init ( standardControls : standardLayoutLines ,
compactControls : compactLayoutLines )
playerView ? . controlsView . layout = customLayout
如果您有需要频繁显示或隐藏的控件,则可以在该控件的布局视图上设置removed
属性。当你改变了你的控件后,在playerView的controlView上调用setNeedsLayout
:
logoLayoutView1 ? . isRemoved = true
playerView ? . controlsView . setNeedsLayout ( )
您还可以自定义几个常规BCOVPUIControlLayout
属性:
controlBarHeight
设置每行控件的大小。horizontalItemSpacing
设置每个控制栏中每个BCOVPUILayoutView
之间的间距。compactLayoutMaximumWidth
确定使用哪一组控件。如果控件视图小于compactLayoutMaximumWidth
,则将使用紧凑控件集,否则将使用标准控件。要更改显示的控件集,您必须创建并安装新的BCOVPUIControlLayout
。可以随时安装新的控件。
有关 PlayerUI 自定义的更多示例,您可以查看 BrightcoveOS GitHub 存储库的 PlayerUI 文件夹中的示例代码:
https://github.com/BrightcoveOS/ios-player-samples
Brightcove Native Player SDK 包括用于在 Apple TV 上的 tvOS 中播放的内置控件。有关将内置电视播放器 UI 与 Brightcove Native Player SDK 结合使用的完整详细信息,请参阅我们的电视播放器指南。
通过将BCOVPlaybackController
上的setAllowsExternalPlayback
属性设置为true
来启用 AirPlay 功能。如果在网络上找到 AirPlay 设备,则播放控件中将显示 AirPlay 按钮。
目前,IMA 是唯一支持 AirPlay 的广告插件,并且仅在使用前贴片和/或后贴片广告时才支持。将 AirPlay 与 Pulse、SSAI 或 FreeWheel 广告插件一起使用可能会导致意外行为。
如果您还想支持 AirPlay 2 并允许选择多个设备进行音频输出,您将需要做一些额外的事情。首先,您需要配置 AVAudioSession ,以便可以设置routeSharingPolicy
。例如:
do {
try AVAudioSession . sharedInstance ( ) . setCategory ( . playback , mode : . moviePlayback , policy : . longFormVideo )
} catch {
print ( " Error setting AVAudioSession category " )
}
您还需要通过MPRemoteCommandCenter
配置至少一个播放命令。至少您需要配置pauseCommand
和playCommand
。例如:
let center = MPRemoteCommandCenter . shared ( )
center . pauseCommand . addTarget { _ in
playbackController . pause ( )
return . success
}
center . playCommand . addTarget { _ in
playbackController . play ( )
return . success
}
设备将利用AVRoutePickerView
,它有两个委托方法。这些委托方法传递给BCOVPUIPlayerViewDelegate
。方法有:
func routePickerViewDidEndPresentingRoutes ( _ routePickerView : AVRoutePickerView )
func routePickerViewWillBeginPresentingRoutes ( _ routePickerView : AVRoutePickerView )
用于发现 AirPlay 路由的AVRouteDetector
在BCOVPUIBasicControlView
对象上可用,因此您可以根据需要启用或禁用其routeDetectionEnabled
属性。
根据苹果的文档:“路由检测会显着增加功耗,当不再需要时必须将其关闭。 ”
playerView ? . controlsView . routeDetector . isRouteDetectionEnabled = false
有关将 AirPlay 2 集成到您的应用程序中的更多信息,请参阅将 Airplay 2 集成到您的应用程序中文档。
Native Player SDK 支持交互式显示 360 度球形视频。 360 度视频应使用包含值“equisquare”的“projection”字段属性进行标记。这些视频将以与其他视频相同的方式加载和播放,但它们将显示在 CAMetalLayer 而不是 AVPlayerLayer 中。
注意:“等距矩形”是目前 360 度源视频支持的唯一投影格式。
PlayerUI 还内置了对 Video 360 的支持,提供默认平移手势、视图的陀螺仪运动检测以及在播放 Video 360 资源时出现的新 Video 360 按钮。此按钮仅出现在 iPhone 上,可让您在普通视图和“VR 护目镜”视图之间切换,其中屏幕分为两部分,为每只眼睛渲染相同的场景,以便该设备可以在头部使用。安装配置。在 iPad 上,不需要 Video 360 按钮,因为只有一种操作模式:支持平移手势的运动检测。
支持 Video 360 就像播放视频一样简单。当检测到“投影”字段属性时,Native Player SDK 将自动处理在 Metal 中设置和显示视频,并在适当时安装 Video 360 按钮。
如果您在 Video Cloud 外部播放 360 度视频,请务必将“投影”属性添加到BCOVVideo
对象,其值为“equirectangular”。
为了通过 VR Goggles 模式提供最佳的用户体验,您应该使用BCOVPUIPlayerViewDelegate
方法来检测何时启用此模式。这允许您强制设备进入横向(因为这是对 VR 护目镜视图有意义的唯一方向)。
以下代码显示了在正常 360 度视图和 VR 护目镜模式之间来回切换时如何处理强制方向更改。
// Set this to YES when displaying a VR goggles video
var landscapeOnly = false
// UIViewController override:
// Lets us control the orientation of the device
override var supportedInterfaceOrientations : UIInterfaceOrientationMask {
get {
if landscapeOnly {
return . landscape
}
return . all
}
}
// BCOVPUIPlayerViewDelegate method
func didSetVideo360NavigationMethod ( _ navigationMethod : BCOVPUIVideo360NavigationMethod ,
projectionStyle : BCOVVideo360ProjectionStyle ) {
switch projectionStyle {
case . normal :
print ( " BCOVVideo360ProjectionStyleNormal " )
landscapeOnly = false
case . vrGoggles :
print ( " BCOVPUIVideo360NavigationDeviceMotionTracking " )
landscapeOnly = true
let currentDeviceOrientation = UIDevice . current . orientation
switch currentDeviceOrientation {
case . landscapeLeft ,
. landscapeRight :
// all good
break
default :
// switch orientation
UIDevice . current . setValue ( UIInterfaceOrientation . landscapeLeft . rawValue , forKey : " orientation " )
break
}
break
default :
break
}
UIViewController . attemptRotationToDeviceOrientation ( )
}
PlayerUI 将安装手势来处理 360 度视频周围的导航,但如果您使用自己的控件,则可以自己设置虚拟摄像机的视图参数。 BCOVPlaybackController
协议的viewProjection
属性允许您设置这些参数。该属性是一个BCOVVideo360ViewProjection
类,具有基本的虚拟摄像机设置,如pan
、 tilt
和zoom
。要更改设置,请复制当前实例,更改新实例上的设置,然后将其分配回viewProjection
属性。
iOS 版 Brightcove Player SDK 的入口点是BCOVPlayerSDKManager
单例对象。该管理器处理插件组件的注册和一些其他内务任务,但它主要充当对象工厂。您的应用程序的视图控制器获取对 Manager 的引用,并使用它来创建BCOVPlaybackController
。播放控制器的view
属性公开一个包含 AVPlayerLayer 对象的 UIView,该对象最终在屏幕上呈现视频内容。播放控制器还接受BCOVPlaybackControllerDelegate
,您可以实现它来响应各种视频播放事件。
播放控制器提供影响当前视频播放的方法和属性。但是,在内部,播放控制器委托给BCOVPlaybackSession
对象。播放会话执行准备和播放视频内容的实际工作,并包含视频的元数据和AVPlayer
。播放控制器具有从当前播放会话前进到下一个播放会话的机制,可以在视频结束时自动进行,也可以通过方法调用手动进行。一旦播放控制器前进到新会话,先前的会话将被丢弃并且不能再次使用。
播放控制器还有另外两个元素: BCOVPlaybackSessionProvider
和BCOVPlaybackSessionConsumer
列表。顾名思义,播放会话提供者负责创建播放会话并将它们传递给播放控制器。然后,回放控制器将会话传送给列表中的每个回放会话消费者。会话提供者和会话使用者 API 都是为插件开发人员使用而设计的,本文档中没有详细说明。
除了上述类提供的播放功能之外,还有一些值类。它们用于保存特定于 iOS 版 Player SDK 的数据。其中每一个都在下面其各自的部分中进行了更详细的描述。
适用于 iOS 的 Brightcove Player SDK 在BCOVPlaybackController
上提供播放、暂停和搜索方法。使用这些方法而不是使用 AVPlayer 等效方法非常重要。在它们的默认实现中,这些对象将调用直接转发到 AVPlayer 上的相应方法。但是,如果您使用插件,它们可能会覆盖默认行为以添加功能。例如,如果使用广告插件,第一次调用playbackController.play()
可能会导致在开始内容之前播放预滚动。要了解有关插件如何覆盖默认行为的更多信息,请参阅每个插件 README.md 或检查插件可能添加的BCOVSessionProviderExtension
上的类别扩展。
直接在 AVPlayer 上调用播放、暂停或搜索可能会导致未定义的行为。
要为 AVPlayer 设置自定义播放速率,您可以使用BCOVPlaybackController
上的playbackRate
属性。使用此属性设置播放速率而不是直接在 AVPlayer 上设置它很重要。
尝试将playbackRate
设置为0 或更低的值将导致该值被设置为1.0。如果 AVPlayer 的currentItem
不支持canPlaySlowForward
(对于小于 1 的值)或canPlayFastForward
(对于大于 1 的值),则将使用默认播放速率 1.0。广告播放不会受到影响。
如果为playbackRate
设置了自定义值,则每个AVPlayerItem
的audioTimePitchAlgorithm
将设置为AVAudioTimePitchAlgorithmTimeDomain
。或者,您可以为audioTimePitchAlgorithm
设置自己的值,如下所示:
func playbackController ( _ controller : BCOVPlaybackController ,
playbackSession session : BCOVPlaybackSession ,
didReceive lifecycleEvent : BCOVPlaybackSessionLifecycleEvent ) {
if lifecycleEvent . eventType == kBCOVPlaybackSessionLifecycleEventReady {
session . player . currentItem ? . audioTimePitchAlgorithm = . varispeed
}
}
您可以在此处阅读有关audioTimePitchAlgorithm
的更多信息。
自 6.12.0 版本以来,iOS SDK 使用了 AVQueuePlayer 来处理队列中下一个视频的预加载。
但是,您可能希望更好地控制在播放列表中预加载即将播放的视频。一种可能的方法是使用两个播放控制器对视频列表进行双缓冲,例如:
playbackController1.setVideos([videos.firstObject])
)playbackController:didProgressTo:
委托方法确定当前视频是否已经进展到您想要开始预加载下一个视频的位置对于工作示例,您可以从我们的播放器示例存储库下载我们的 VideoPreloading 示例应用程序。
注意:您可能需要考虑客户端设备上的可用内存量及其连接速度。如果不在 Wifi 上,预加载视频可能会影响当前视频的网络资源。
适用于 iOS 的 Brightcove Player SDK 使客户端能够将多个 url 和传输类型 ( BCOVSource
) 附加到单个视频 ( BCOVVideo
)。例如,如果播放服务正在检索您的视频,则单个视频可能会混合使用 HLS 或 MP4 版本以及 HTTP 和 HTTPS 版本。 选择这些源中的哪一个是由源选择策略块确定的。默认源选择策略将选择每个BCOVVideo
上的第一个 HLS BCOVSource
,其中 HTTPS 源优先于 HTTP。
可以通过创建BCOVBasicSessionProviderOptions
并使用它创建BCOVBasicSessionProvider
来覆盖源选择。例如:
let sdkManager = BCOVPlayerSDKManager . sharedManager ( )
let options = BCOVBasicSessionProviderOptions ( )
options . sourceSelectionPolicy = < policy >
let provider = sdkManager . createBasicSessionProvider ( withOptions : options )
let playbackController = sdkManager . createPlaybackController ( withSessionProvider : provider , viewStrategy : nil )
如果此默认选择策略不适合您,则有几种选择来源的替代方法:
如果通过播放服务从视频云检索视频,请在调用playbackController.setVideos()
之前,使用BCOVVideo
上的更新方法仅包含所需的源(有关更多信息,请参阅“值”部分)。
您可以使用帮助器方法[BCOVBasicSourceSelectionPolicy sourceSelectionHLSWithScheme:scheme]
创建首选特定方案的策略。这是用于创建首选 HTTPS 的默认源选择策略的方法。
与更新视频对象类似,您也可以实现自己的源选择块。
options . sourceSelectionPolicy = { ( video : BCOVVideo ? ) -> BCOVSource ? in
< Check video . sources for source >
< Return source >
}
请注意,App Store 对 MP4 视频的使用有限制。查看最新的 Apple 开发者信息以了解详细信息。
适用于 iOS 的 Brightcove Player SDK 提供了一种设置视频首选比特率的方法。您可以创建一个 BCOVPreferredBitrateConfig 对象,其中包含所需的比特率选项,以及为显示选项而创建的视图控制器的一些配置。
菜单的标题是可选的。比特率选项是 NSDictionary 的数组,每个字典都有一个键:值对。键将用作选项名称,值是一个 NSNumber,其中该选项的比特率以 bps(每秒位数)为单位。您输入的比特率是可以映射到视频资源演绎的比特率的值。您可以在摄取配置文件最佳实践中了解有关演绎的更多信息。
这是一个例子:
let bitrates = [
[ " Auto " : NSNumber ( 0 ) ] ,
[ " Setting 1 " : NSNumber ( 518100 ) ] ,
[ " Setting 2 " : NSNumber ( 2596000 ) ]
]
let options = BCOVPUIPlayerViewOptions ( )
options . preferredBitrateConfig = BCOVPreferredBitrateConfig ( menuTitle : " Select an Option " ,
andBitrateOptions : bitrates )
当最终用户选择其中一个选项时,当前 AVPlayerItem 的 PreferredPeakBitRate 属性将设置为该选项的值。如果视频位于播放列表中,则播放的下一个视频也将设置 PreferredPeakBitRate 值。
为 PreferredPeakBitRate 设置非零值后,您可能不会注意到质量差异,直到 AVPlayer 到达其当前缓冲缓存的末尾。
您还可以使用configWithMenuTitle:bitrateOptions:andIndexofInitialSelection:
初始值设定项,它提供了设置首选初始值索引的功能。该索引应与bitrateOptions
数组中所需选项的索引相关。
您还可以在BCOVPlaybackController
对象上使用setPreferredPeakBitRate:
方法以编程方式设置当前和未来会话的首选比特率。
注意:必须为最终用户提供返回到 PreferredPeakBitRate 默认值 (0) 的方法。您可以通过提供比特率值为 0 的选项来完成此操作。如果您不提供比特率选项 0,“自动”选项将附加到最终用户的选项列表中。
请参阅 Apple 关于 PreferredPeakBitRate 的文档以了解更多信息。
适用于 iOS 的 Brightcove Player SDK 提供了两种获取播放信息的机制。播放控制器提供了一个实现BCOVPlaybackControllerDelegate
的委托属性。委托可以实现这些可选方法来获取播放元数据(例如进度、持续时间更改和其他事件)的通知。如果安装了广告插件,它也可以使用此委托来提供有关广告播放的信息。生命周期事件委托方法提供事件来指示播放状态的变化。例如,当播放器从暂停状态进入播放状态时,将通过kBCOVPlaybackSessionLifecycleEventPlay
事件调用生命周期事件委托方法。默认生命周期事件在BCOVPlaybackSession
中声明。 Brightcove 提供的插件添加了每个插件中定义的附加生命周期事件。
播放控制器允许单个委托。在许多情况下,这足以检索信息;委托实现可以根据需要将值和事件传播到应用程序的不同部分。在需要多个委托的情况下(如开发插件时的情况), BCOVPlaybackSessionConsumer
委托提供与BCOVPlaybackControllerDelegate
方法等效的功能,包括广告数据。
以下是如何使用BCOVPlaybackSessionConsumer
创建分析插件的示例:
class XYZAnalytics : NSObject , BCOVPlaybackSessionConsumer {
func playbackSession ( _ session : BCOVPlaybackSession , didProgressTo progress : TimeInterval ) {
//react to progress event
}
}
要使用该插件:
let sdkManager = BCOVPlayerSDKManager . sharedManager ( )
let controller = sdkManager . createPlaybackController ( )
let analytics = XYZAnalytics ( )
controller . add ( analytics )
当应用程序体验网络中断时,如果中断持续时间太长,则BCOVPlaybackController
使用的AVPlayer
可能会停止尝试恢复。如果发生这种情况,将使用kBCOVPlaybackSessionLifecycleEventFailedToPlayToEndTime
事件来调用生命周期代表方法。当此事件发生时,播放将不会自动恢复。为了从此事件中恢复,您需要检测网络何时在客户端代码中恢复。
确定网络已恢复后,您可以使用playbackController.resumeVideo(at:withAutoPlay:)
重新定位播放器。您将需要跟踪要恢复的位置。玩家将尽最大努力抑制生命周期事件和进度事件,以防止广告重播或涉足分析。
打电话给playbackController.resumeVideo(at:withAutoPlay:)
,玩家将发送一个类型的kBCOVPlaybackSessionLifecycleEventResumeBegin
的生命周期事件。如果此操作成功,则将发送kBCOVPlaybackSessionLifecycleEventResumeComplete
,否则将发送kBCOVPlaybackSessionLifecycleEventResumeFail
。
您必须等待拨打playbackController.resumeVideo(at:withAutoPlay:)
第二次,直到您从上一个电话中收到kBCOVPlaybackSessionLifecycleEventResumeComplete
或kBCOVPlaybackSessionLifecycleEventResumeFail
。在向用户发出消息表明他们的网络过于不稳定之前,您可能希望施加重试限制。
当AVPlayer
仍然能够访问网络时,但是由于网络太慢,视频摊位时,Lifecycle委托方法将使用kBCOVPlaybackSessionLifecycleEventPlaybackStalled
事件来调用。当播放能够恢复时,将使用kBCOVPlaybackSessionLifecycleEventPlaybackRecovered
召集生命周期代表方法。这些事件仅涵盖正常播放停止并且不涵盖视频寻求或初始负载期间发生缓冲的情况。
当视频最初加载时,发生搜索或由于慢网络引起的播放摊位时,将使用kBCOVPlaybackSessionLifecycleEventPlaybackBufferEmpty
事件来调用Lifecycle委托方法。当播放能够恢复时,将使用kBCOVPlaybackSessionLifecycleEventPlaybackLikelyToKeepUp
事件来调用Lifecycle代表方法。
除非否则明确记录了iOS的播放器SDK中的所有类,否则均未将其设计为子分类。创建一个没有明确设计为子分类的任何SDK类的子类,尤其是任何值类都可能导致不可预测的行为。
这些类也称为“模型对象”( BCOVPlaylist
, BCOVVideo
, BCOVSource
, BCOVCuePoint
, BCOVCuePointCollection
)用于表示iOS播放器SDK中的数据。至关重要的是要了解这些数据类型被视为值,而不是身份。这样,我们的意思是,如果您有两个具有完全相同数据的值类的实例,则它们代表相同的想法或价值,即使它们在技术上是两个不同的对象,在单独的内存地址上。换句话说,SDK代码和您的客户端代码都不应使用标识比较(“指针平等”)与值对象。取而代之的是,每个值类都实现-isEqual:
并提供特定于类的平等方法过载,这两种方法都应使用。
这是不好的:
if myVideo == session . video // Could lead to bugs!
这些是好的(在功能上等效):
if myVideo . isEqual ( session . video )
if myVideo . isEqual ( toVideo : session . video )
iOS播放器SDK的内部质量可能会进行记忆价值或制作防御性副本,因此依靠指针地址检查平等,最终会导致您的痛苦。
iOS播放器SDK中价值类的另一个质量是它们是不可变的。一旦有一个值的实例,就不应尝试以任何方式颠覆这种不变性,因为它可能导致不可预测的行为。如果您希望以某种方式“修改”一个值,那么您唯一的求助是创建一个新值。为了帮助客户获得“修改”值的方便起见,每个值类都提供了一个-update:
方法,该方法允许您在原始值的可变副本上操作。
这是使用此方法创建现有视频对象的“修改”版本的示例,但具有不同的属性:
let video1 : BCOVVideo // (properties include a key "foo" whose value is "bar")
let video2 = video1 . update { ( mutableVideo : BCOVMutableVideo ) in
mutableVideo . properties = [ " foo " : " quux " ]
}
if let foo1 = video1 . properties [ " foo " ] ,
let foo2 = video2 . properties [ " foo " ] {
print ( " foo is ( foo1 ) " ) // prints "foo is bar"
print ( " foo is ( foo2 ) " ) // prints "foo is quux"
}
// Both video1 and video2 are still immutable objects:
video1 . properties = [ " foo " : " fail " ] // causes compiler error
video2 . properties = [ " foo " : " fail " ] // causes compiler error
如您在示例中所看到的那样, -update
方法调用尚未更改video1
。取而代之的是,此方法返回video1
的副本,除了块主体中进行的修改。您绝对不应允许可变的副本逃脱块(例如通过将其分配给__block
变量),而是在进行修改后使用-update
方法返回的不变对象。
播放服务类, BCOVPlaybackService
,提供了通过BrightCove播放API检索BrightCove视频资产和播放列表的功能,包括丰富的元数据,例如文本轨道,预览和缩略图。以下示例显示了如何使用视频ID检索视频。还提供了使用该视频的参考ID检索视频或播放列表的方法。
[ 1 ] let kPolicyKey = " ... "
let kAccountId = " ... "
let kVideoId = " ... "
let sdkManager = BCOVPlayerSDKManager . sharedManager ( )
let playbackController = sdkManager . createPlaybackController ( )
self . playbackController = playbackController
view . addSubview ( playbackController . view )
let playbackService = BCOVPlaybackService ( withAccountId : kAccountId ,
policyKey : kPolicyKey )
let configuration = [
BCOVPlaybackService . ConfigurationKeyAssetID : kVideoId
]
playbackService . findVideo ( withConfiguration : configuration ,
queryParameters : nil ) { ( video : BCOVVideo ? ,
jsonResponse : Any ? ,
error : Error ? ) in
if let video {
self . playbackController ? . setVideos ( [ video ] )
self . playbackController ? . play ( )
}
}
注意:如果您使用的是播放授权服务,请查看与该功能相关的此读数的部分。
对于返回播放列表的BCOVPlaybackService
方法,您可以通过指定参数字典中的限制和偏移参数来请求部分播放列表或从播放列表中“页面”。限制指定将返回的最大视频数量,偏移量将索引指定为播放列表,将返回视频。
例如,如果您有一个带有100个视频的播放列表,则可以从视频编号10开始请求6个视频,如下所示:
let parameters = [
" limit " : 6 ,
" offset " : 10
]
let configuration = [
BCOVPlaybackService . ConfigurationKeyAssetID : kVideoId
]
playbackService . findVideo ( withConfiguration : configuration ,
queryParameters : parameters ) { ( video : BCOVVideo ? ,
jsonResponse : Any ? ,
error : Error ? ) in
if let video {
self . playbackController ? . setVideos ( [ video ] )
self . playbackController ? . play ( )
}
}
使用视图策略构造了BCOVPlaybackController
对象,该对象允许您作为SDK的客户端定义从播放控制器的视图属性返回的确切UIVIEW对象。当使用影响播放控制器视图的插件时,这一点很重要,例如广告插件将视频视图与广告视图叠加在一起。许多应用程序无需创建视图策略,并且在创建新的播放控制器时可以简单地通过nil
。这将在播放控制器中创建标准视频视图。
BCOVPlaybackControllerViewStrategy
TYPEDEF别名(和文档)这个更复杂的块签名:
UIView *(^)(UIView *videoView, id playbackController);
该签名描述了一个返回Uiview的Objective-C块,并采用两个参数:一个Uiview和一个播放控制器。返回值是播放控制器的视图属性将指向的Uiview对象。第一个参数是包含视频层的Uiview,Uiview将显示视频。第二个参数是给出视图策略的播放控制器对象,播放控制器可用于添加必要的会话消费者,例如视频控件或广告控件。
视图策略实施的示例:
let viewStrategy = { ( videoView : UIView ? , playbackController : BCOVPlaybackController ? ) in
guard let videoView ,
let playbackController else {
return UIView ( )
}
// Create some custom controls for the video view,
// and compose both into a container view.
[ 1 ] let myControlsView = MyControlsView ( ) // Conforms to BCOVPlaybackSessionConsumer
[ 2 ] let controlsAndVideoView = UIView ( )
[ 3 ] controlsAndVideoView . addSubview ( videoView )
controlsAndVideoView . addSubview ( myControlsView )
// Compose the container with an advertising view
// into another container view.
[ 4 ] let adView = SomeAdPluginView ( ) // Conforms to BCOVPlaybackSessionConsumer
[ 5 ] let adAndVideoView = UIView ( )
[ 6 ] adAndVideoView . addSubview ( controlsAndVideoView )
adAndVideoView . addSubview ( adView )
[ 7 ] playbackController . add ( myControlsView )
playbackController . add ( adView )
// This container view will become `playbackController.view`.
return adAndVideoView
}
将代码分解为步骤:[1]创建一个符合BCOVPlaybackSessionConsumer
协议的自定义控件视图。 BCOVPlaybackSessionConsumer
协议允许除了广告外,还可以为每个视频接收基本的播放信息。 [2]为视频视图和自定义控件创建一个容器视图。 [3]作为视频容器和自定义控件的子视图添加。层次结构的组成与添加视图相同的顺序。 [4]创建一个符合BCOVPlaybackSessionConsumer
协议的AD控件视图。 [5]为视频视图和控件创建一个容器视图以及广告视图。 [6]作为一个子视图添加视频容器和广告控件视图。 [7]使用块返回的播放控制器对象,注册自定义控件视图和AD控件视图作为会话消费者。
有一个警告要使用视图策略:您不得从视图策略块中访问播放控制器的view
属性。由于被称为块,因为首次访问了播放控制器的view
属性,因此在视图策略块中再次访问view
属性会导致您的程序崩溃。
默认情况下,当将iOS应用程序发送到后台或锁定设备时,iOS将暂停任何正在播放的视频。要更改此行为,请将BCOVPlaybackController
对象的allowsBackgroundAudioPlayback
属性设置为true
。 (默认值是false
,指示播放将在后台暂停。)
您还应该遵循Apple在技术问答QA1668中设定的指南,以为您的应用程序设置适当的背景模式和音频会话类别。
重要的是,在将应用程序切换到背景之前,将AVPlayerLayer
从AVPlayer
脱离(并在应用程序返回前景时重新连接)。 BrightCove Player SDK将为您处理此操作时,将allowsBackgroundAudioPlayback
设置为true
。
最后,在播放背景视频(尤其是使用播放列表时)时,您应该使用iOS MPRemoteCommandCenter
API在锁定屏幕和控制中心中为用户播放控制。
要在应用程序中启用图片中的图片,请在实例化BCOVPUIPlayerView
对象时,将BCOVPUIPlayerViewOptions
对象设置为true
的showPictureInPictureButton
属性。然后,图片中的图片按钮将显示在任何支持它的设备的控件栏中。
要使图片中的图片正确工作,您将需要确保在项目的“目标功能”选项卡的Background Modes
部分中将Audio, AirPlay, and Picture in Picture
模式中转动。您还应该遵循Apple在技术问答QA1668中设定的指南,以为您的应用程序设置适当的背景模式和音频会话类别。
AVPictureInPictureControllerDelegate
方法通过BCOVPUIPlayerViewDelegate
传递。这些方法是:
func pictureInPictureControllerDidStartPicture ( inPicture pictureInPictureController : AVPictureInPictureController )
func pictureInPictureControllerDidStopPicture ( inPicture pictureInPictureController : AVPictureInPictureController )
func pictureInPictureControllerWillStartPicture ( inPicture pictureInPictureController : AVPictureInPictureController )
func pictureInPictureControllerWillStopPicture ( inPicture pictureInPictureController : AVPictureInPictureController )
func picture ( _ pictureInPictureController : AVPictureInPictureController , failedToStartPictureInPictureWithError error : Error )
func picture ( _ pictureInPictureController : AVPictureInPictureController , restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler : ( Bool ) -> Void )
有关更多信息,请参见Apple的AvpictureInPictureControllerDelegate文档。
要实现自己的图片中的行为,请将BCOVPlaybackController
的allowsBackgroundAudioPlayback
属性设置为false
,并保留BCOVPlaybackController
的pictureInPictureActive
属性,并使用图片中的图片状态进行更新。如果您使用的是AVPictureInPictureController
,则可以使用pictureInPictureControllerDidStartPicture(inPicture:)
和pictureInPictureControllerDidStopPicture(inPicture:)
委托方法更新此属性。
您可以在自定义播放器文档中的Apple采用图片中了解有关在Apple采用图片中插入图片的更多信息。
使用带有混合格式的视频播放列表,并带有图片中的图片,将导致每个视频之间的图片窗口关闭。
iOS和iPados 14引入了自动图片中的行为,可以在Settings > General > Picture in Picture
中打开/关闭。为了使此功能按预期工作,播放器视图必须等于屏幕宽度,并且高度必须至少为0.57与宽度的比率(16:9或更大)。如果您的播放器视图的宽度或高度小于这些值时,则在应用程序进入背景时可能不会自动触发。
重要的是:IMA,Freewheel,Pulse和SSAI插件每个处理图片中的功能都不同。查看每个插件中的图片中的图片部分,以获取更多信息。
缩略图寻求使用户可以沿时间轴拖动游戏头,并将缩略图视为相关内容的预览。这使用户能够快速导航视频文件并找到他们感兴趣的内容。
Apple还将此功能称为Trick Play,并在其HLS创作规范中引用。
该功能默认启用。如果您想禁用缩略图寻求,则可以通过将BCOVPlaybackController
上的thumbnailSeekingEnabled
属性设置为false
来做到这一点。
playbackController . thumbnailSeekingEnabled = false
您可以通过使用您的BCOVPUIPlayerView
或BCOVTVPlayerView
来自定义缩略图预览的布局。
在iOS上,您可以调整高度,宽度和垂直偏移:
func setUpPlayerView ( ) {
let playerView = BCOVPUIPlayerView ( playbackController : nil )
playerView ? . delegate = self
...
}
// MARK: BCOVPUIPlayerViewDelegate
func playerViewShouldDisplayThumbnailPreview ( withRect playerView : BCOVPUIPlayerView ) -> CGRect {
let width : CGFloat = 100
let height : CGFloat = 56
let verticalOffset : CGFloat = - 60
var modifier : CGFloat = 1
if UIDevice . current . userInterfaceIdiom == . pad {
modifier = 2
}
return CGRect ( x : 0 , y : verticalOffset * modifier , width : width * modifier , height : height * modifier )
}
在TVOS上,您可以调整高度和宽度:
func setUpPlayerView ( ) {
let playerView = BCOVTVPlayerView ( options : nil )
playerView ? . delegate = self
...
}
// MARK: BCOVTVPlayerViewDelegate
func playerViewShouldDisplayThumbnailPreview ( withSize playerView : BCOVTVPlayerView ) -> CGSize {
var size = self . view . frame . size
size . width = size . width / 6
size . height = size . height / 6
return size
}
如果手动构造BCOVVideo
对象,则可以将用于缩略图WebVTT源的URL设置为:
if let url = URL ( string : " https://mydomain.com/master.m3u8 " ) {
var video = BCOVVideo . video ( withURL : url )
video = video . update ( { ( mutableVideo : BCOVMutableVideo ) in
mutableVideo . thumbnailVTTURL = URL ( string : " https://mydomain.com/thumbnail.webvtt " )
} )
}
寻求缩略图仅用于在线视频;下载/离线视频不支持此功能。
BCOVPlaybackController
可以通过调用insertVideo:afterVideoAtIndex:
例如:
// This will insert the new video after the first video in the queue
playbackController . insert ( videoToInsert , afterVideoAt : 0 )
您可以使用两种代表方法来提醒请求的成功或失败。
func playbackController(_ controller: BCOVPlaybackController, didInsert video: BCOVVideo, at index: UInt)
func playbackController(_ controller: BCOVPlaybackController, failedToInsert video: BCOVVideo)
通用流并发(GSC)是一项服务,该服务确定是否基于观看者的主动播放会话和预设并发限制允许播放。通过边缘播放授权(EPA)服务请求该服务。在此使用了相同的JWT来检索视频,并应包括uid
索赔, climit
索赔以及可选的sid
索赔。此功能必须在您的ACCCOUNT中启用。
默认情况下,在SDK中未启用通用流并发。如果要启用它,请将BCOVPlaybackController
的streamConcurrencyEnabled
属性设置为true
。
playbackController . streamConcurrencyEnabled = true
sid
值可以包含在JWT中,也可以作为BCOVPlaybackController
选项发送,这两个都是可选的。 JWT中的sid
值优先于BCOVPlaybackController
选项。
playbackController . options [ kBCOVAuthHeartbeatPropertyKeySessionId ] = " sessionId "
在达到并发限制时,已将一种新的代表方法添加到BCOVPlaybackControllerDelegate
中以检索活动会话。
func playbackController ( _ controller : BCOVPlaybackController ,
playbackSession session : BCOVPlaybackSession ,
didReachMaxConcurrency sessions : [ AnyHashable : Any ] ) {
print ( " ( sessions ) " )
}
播放错误通常通过播放控制器的视频播放事件进行处理和报告。如果您需要更深入地研究特定视频或应用程序会话的问题,则可以利用BrightCove Player SDK的会话ID 。会话ID是BCOVPlayerSDKManager
的属性,您可以这样检索:
let sdkSessionID = BCOVPlayerSDKManager . sharedManager ( ) . sessionID
会话ID是一个唯一的字符串,在应用程序生命周期中不会改变。该字符串与BrightCove指标服务器一起报告了其他各种分析数据。如果您在特定的应用程序实例或视频中遇到问题,则可以记录会话ID并将其发送回您自己的公司服务器。然后,您可以将会话ID,视频ID和任何其他相关数据发送给BrightCove服务工程师,以帮助诊断任何问题。
如果您需要组合播放器SDK插件,例如,将字幕添加到受DRM保护的视频中,该视频播放由Google IMA管理的广告,则创建了每个插件的BCOVSessionProviders
并将其链接在一起,并将链条用于构造BCOVPlaybackController
。
let sdkManager = BCOVPlayerSDKManager . sharedManager ( )
let imaSettings = IMASettings ( )
imaSettings . ppid = kIMAPublisherID
if let languageCode = NSLocale . current . languageCode {
imaSettings . language = languageCode
}
let renderSettings = IMAAdsRenderingSettings ( )
renderSettings . linkOpenerPresentingController = self
let adsRequestPolicy = BCOVIMAAdsRequestPolicy . videoPropertiesVMAPAdTagUrl ( )
// create the sidecar subtitles session provider. it has no upstream session provider.
let sidecarSessionProvider = sdkManager . createSidecarSubtitlesSessionProvider ( withUpstreamSessionProvider : nil )
// create a fairplay session provider with the sidecar session provider as its upstream session
let authProxy = BCOVFPSBrightcoveAuthProxy ( withPublisherId : nil ,
applicationId : nil )
let fairPlaySessionProvider = sdkManager . createFairPlaySessionProvider ( withAuthorizationProxy : authProxy ,
upstreamSessionProvider : sidecarSessionProvider )
// create the IMA session provider with an upstream sidecar subtitles session provider.
let imaSessionProvider = sdkManager . createIMASessionProvider ( with : imaSettings ,
adsRenderingSettings : renderSettings ,
adsRequestPolicy : adsRequestPolicy ,
adContainer : playerView ? . contentOverlayView ,
viewController : self ,
companionSlots : nil ,
upstreamSessionProvider : fairPlaySessionProvider )
开发人员可以控制AVPlayer
使用的正向播放缓冲区的大小。这是通过在AVPlayerItem
类中设置preferredForwardBufferDuration
属性来完成的。
默认情况下,BrightCove本地播放器SDK以preferredForwardBufferDuration
而无需牺牲播放质量的方式来优化整体带宽。可以用自己的价值观覆盖这种行为。
每个人都为带宽付费,因此在不影响播放质量的情况下减少带宽消耗非常重要。新款版本5.2.0,BrightCove本地播放器SDK在视频播放时动态地管理您的缓冲尺寸。
在iOS 10之前, AVPlayer
可以尽可能多地缓冲视频数据,可达约50兆字节。对于视频观看模型来说,这是可以的,在该模型中,用户选择视频然后观看直到结束,但是现在许多现代应用程序都会使用自动播放“取笑”视频,希望在几秒钟后确保参与度。许多用户只是转到不同的视频。通过激进的缓冲,您最终可以得到几分钟的缓冲视频,这些视频被每个视频印象所抛弃。
BrightCove本地播放器SDK通过使用小基线缓冲区启动视频来解决此问题,然后在用户观看更多视频时将其增加。一定的一点之后,缓冲区的尺寸被封顶,因为它使其太大不实用或有用。
如果要保持BrightCove本地播放器SDK的默认行为,但要修改用于缓冲区大小的最小值和最大值,则在设置BCOVPlaybackController
时可以执行以下操作:
// Create mutable dictionary to hold new values
if var options = playbackController . options {
// Set new values in dictionary
options [ kBCOVBufferOptimizerMethodKey ] = BCOVBufferOptimizerMethod . default . rawValue
options [ kBCOVBufferOptimizerMinimumDurationKey ] = minValue
options [ kBCOVBufferOptimizerMaximumDurationKey ] = maxValue
// Set new dictionary in your playback controller
playbackController . options = options
}
这些选项应在调用playbackController.setVideos()
之前先设置这些选项。
min
和max
:
AVPlayer
可能会缓冲无法查看的数据。AVPlayerItem
中的特殊值,该值告诉AVPlayer
确定其自身的缓冲区大小。如果您在当前的播放会话中不需要任何缓冲区优化,则可以使用相同的技术,但是将“ optimziation方法”设置为“无”,如下所示:
// Create mutable dictionary to hold new values
if var options = playbackController . options {
// Set new values in dictionary
options [ kBCOVBufferOptimizerMethodKey ] = BCOVBufferOptimizerMethod . none
// Set new dictionary in your playback controller
playbackController . options = options
}
将方法设置为.none
,iOS将保持对前向缓冲区大小的完全控制。
如果要设置自己的缓冲区大小进行播放,请首先关闭上一节中所述的缓冲区优化。然后,您可以实现以下BCOVPlaybackController
委托方法:
func playbackController ( _ controller : BCOVPlaybackController , didAdvanceTo session : BCOVPlaybackSession ) {
if let currentItem = session . player . currentItem {
// Set your preferredForwardBufferDuration value here.
currentItem . preferredForwardBufferDuration = newPreferredForwardBufferDurationValue
}
}
如果要随着时间的推移动态更改缓冲区大小,则可以设置session.player.currentItem.preferredForwardBufferDuration
在BCOVPlaybackController
的进度委托方法中,以类似的方式:
func playbackController ( _ controller : BCOVPlaybackController , playbackSession session : BCOVPlaybackSession , didProgressTo progress : TimeInterval ) {
if let currentItem = session . player . currentItem {
// Set your preferredForwardBufferDuration value here.
currentItem . preferredForwardBufferDuration = newPreferredForwardBufferDurationValue
}
}
注意:Apple专门将“首选”放入preferredForwardBufferDuration
中,因为您可以设置所需的任何值,但是总的来说, AVPlayer
播放器只能将其用作指南。还要记住,将其设置为零将完全控制缓冲区大小到AVPlayer
。
您可以使用avplayerviewController,而不是Bcovplaybacksession类使用的Avplayerlayer。使用AvplayerviewController允许玩家使用本机iOS和TVOS播放器控件,但是这种方法存在局限性(请参见下文)。
要使用AvplayerViewController,您可以设置一个名为kBCOVAVPlayerViewControllerCompatibilityKey
的BCOVPLAYBACKCONTROLLER字典属性:
let sdkManager = BCOVPlayerSDKManager . sharedManager ( )
let playbackController = sdkManager . createPlaybackController ( )
if var mutableOptions = playbackController . options {
// To use the AVPlayerViewController
mutableOptions [ kBCOVAVPlayerViewControllerCompatibilityKey ] = true
// To use the BCOVPlaybackSession's AVPlayerLayer
// mutableOptions[kBCOVAVPlayerViewControllerCompatibilityKey] = false
playbackController . options = mutableOptions
}
KBCOVAVPLAYERVIEW CONTROLLERCATIOMEKEY的默认值是false
,这意味着在没有此字典属性的情况下创建的BcovPlayBackController明确设置将使用BcovplayBacksession的AvplayerLayer默认情况下使用Bcovplaybacksession。
使用AvplayerViewController时,BrightCove IMA,Freewheel,Pulse和Ssai AD插件是兼容的。您可以将AvplayerviewController的contentOverlayView
用于显示ADS的视图(不适用于SSAI)。
您可能希望在广告播放之前和之后隐藏/显示AvplayerviewController的播放控件:
func playbackController ( _ controller : BCOVPlaybackController ,
playbackSession session : BCOVPlaybackSession ,
didEnter adSequence : BCOVAdSequence ) {
avpvc . showsPlaybackControls = false
}
func playbackController ( _ controller : BCOVPlaybackController ,
playbackSession session : BCOVPlaybackSession ,
didExitAdSequence adSequence : BCOVAdSequence ) {
avpvc . showsPlaybackControls = true
}
使用BrightCove IMA插件的AvplayerviewController和带有“了解更多”按钮的广告时,您需要创建一个额外的Uiview作为AD容器视图。这是因为AvplayerviewController的contentOverlayView
不是交互式的,因此尝试点击“学习更多”按钮不会产生效果。您可以使用playbackController:playbackSession:didEnterAdSequence:
and playbackController:playbackSession:didExitAdSequence:
委托方法显示和隐藏您的广告容器视图。
如果在TVOS上使用IMA,Freewheel,Pulse或SSAI插件,则将为每个AD提示点创建AVInterstitialTimeRange
的数组,并设置在关联的AVPlayerItem
的interstitialTimeRanges
序列上。对于IMA,freewheel和Pulse插件,您需要创建一个播放/暂停手势,以便当广告处于活动状态时,您可以正确暂停并恢复广告,而不会影响视频本身的播放。这是一个例子:
func setUpAdPlayPauseGesture ( ) {
let playPauseGesture = UITapGestureRecognizer ( target : self , action : #selector ( playPauseAd ( _ : ) ) )
playPauseGesture . allowedPressTypes = [ NSNumber ( value : UIPress . PressType . playPause . rawValue ) ]
avpvc . view . addGestureRecognizer ( playPauseGesture )
self . playPauseGesture = playPauseGesture
}
@ objc
func playPauseAd ( _ gesture : UITapGestureRecognizer ) {
if insideAdSequence {
if adPlaying {
playbackController ? . resumeAd ( )
adPlaying = false
} else {
playbackController ? . pauseAd ( )
adPlaying = true
}
} else {
if avpvc . player ? . rate == 0 {
playbackController ? . play ( )
} else {
playbackController ? . pause ( )
}
}
}
func playbackController ( _ controller : BCOVPlaybackController ,
playbackSession session : BCOVPlaybackSession ,
didEnterAdSequence adSequence : BCOVAdSequence ) {
insideAdSequence = true
}
func playbackController ( _ controller : BCOVPlaybackController ,
playbackSession session : BCOVPlaybackSession ,
didExitAdSequence adSequence : BCOVAdSequence ) {
insideAdSequence = false
}
有关显示AD叠加层(例如倒计时),请参阅您使用的AD插件读取文件的AvplayerviewController支持部分。
请注意,由于AVInterstitialTimeRange
的可用性,SSAI的AVPlayerViewController
兼容性是特定于TVO的。您仍然可以对iOS进行播放,但是视频的持续时间将包括所有广告的持续时间。
我们有示例项目,证明了AvplayerviewController与BrightCove iOS SDK使用。您可以在此处找到iOS示例项目和此处的TVOS示例项目。
使用AvplayerviewController时,发送到BrightCove Analytics Server的Video_Engagemention事件将报告player_width和player_height的0。
如果您使用的是播放授权服务,则需要使用播放服务BCOVPlaybackService.ConfigurationKeyAuthToken
配置密钥。
// Video Request
let configuration = [
BCOVPlaybackService . ConfigurationKeyAssetID : videoID ,
BCOVPlaybackService . ConfigurationKeyAuthToken : authToken
]
playbackService . findVideo ( withConfiguration : configuration ,
queryParameters : nil ) { ( video : BCOVVideo ? ,
jsonResponse : Any ? ,
error : Error ? ) in
...
}
// Playlist Request
let configuration = [
BCOVPlaybackService . ConfigurationKeyAssetID : playlistID ,
BCOVPlaybackService . ConfigurationKeyAuthToken : authToken
]
playbackService . findPlaylist ( withConfiguration : configuration ,
queryParameters : nil ) { ( playlist : BCOVPlaylist ? ,
jsonResponse : Any ? ,
error : Error ? ) in
...
}
注意:就播放列表而言,播放列表中的所有视频都必须使用相同的令牌。在随后的版本中,将可能在播放列表中为每个视频分配不同的令牌。您将负责维护视频ID和令牌之间的映射。
配音是在播放控件的开箱即用的支持。默认情况下,如果启用了配音,则BCOVPLAYERUI控制视图将不会自动隐藏。在播放控制器的视图上,使用Double-Tap VoiceOver激活手势将切换控制视图的可见性。在播放控制器的视图上设置了一个关联的accessibilityHint
。可以在您的应用程序中自定义每个BCOVPLAYERUI控件的accessibilityLabel
。
要更改控件视图中任何按钮的accessibilityLabel
值,您必须将对象设置为bcovpuibuttonAccessibilitydelegate这样的BCOVPUIButtonAccessibilityDelegate
:
playerView . controlsView . setButtonsAccessibilityDelegate ( self )
然后,您必须让该对象符合BCOVPUIButtonAccessibilityDelegate
协议,暗示- (NSString *)accessibilityLabelForButton:(BCOVPUIButton *)button isPrimaryState:(BOOL)isPrimaryState
方法类似于此:
func accessibilityLabel ( for button : BCOVPUIButton ,
isPrimaryState : Bool ) -> String ? {
switch button . tag {
case BCOVPUIViewTag . buttonPlayback . rawValue :
return isPrimaryState ? NSLocalizedString ( " Start Playback " , comment : " playback button " ) : NSLocalizedString ( " Pause Playback " , comment : " playback button " )
case BCOVPUIViewTag . buttonScreenMode . rawValue :
return isPrimaryState ? NSLocalizedString ( " Enter Fullscreen " , comment : " screenmode button " ) : NSLocalizedString ( " Exit Fullscreen " , comment : " screenmode button " )
case BCOVPUIViewTag . buttonJumpBack . rawValue :
return nil
case BCOVPUIViewTag . buttonClosedCaption . rawValue :
return nil
case BCOVPUIViewTag . buttonVideo360 . rawValue :
return nil
case BCOVPUIViewTag . buttonPreferredBitrate . rawValue :
return nil
default :
return nil
}
}
如果返回nil
值,则将使用默认值。
可以这样在播放控制器上设置accessibilityHint
:
playbackController . view . accessibilityHint = " Double tap to show or hide controls "
同样,您可以在当前时间和持续时间标签上设置accessibilityLabel
,以及像这样的进度滑块:
playerView . controlsView . durationLabel . accessibilityLabelPrefix = " Total Time "
playerView . controlsView . currentTimeLabel . accessibilityLabelPrefix = " Current Time "
playerView . controlsView . progressSlider . accessibilityLabel = " Timeline "
您可以提供其他语言本地化,Brightcove iOS SDK不支持开箱即用。
+
按钮来添加本地化。为了定义中国播放服务,指标和分析服务器的代理域名,将BCOVGlobalConfiguration
Singleton的chinaProxyDomain
属性设置为完全合格的域名。例如:
BCOVGlobalConfiguration . sharedConfig . chinaProxyDomain = " host.mydomain.com "
在使用本机播放器SDK的任何其他服务之前,请确保设置代理域名。有关详细信息,请参阅BCOVGLOBALCONFIGURATION类参考。
根据您需要如何在音频播放方面执行的应用程序,您可以配置AvauioSession以适合您的特定需求。例如,如果您想支持AirPlay 2和多个音频路线,请参见此读数的“空中播放”部分。
可以这样的基本avauiosession进行配置:
var categoryError : NSError ?
var success : Bool
do {
// see https://developer.apple.com/documentation/avfoundation/avaudiosessioncategoryplayback
try AVAudioSession . sharedInstance ( ) . setCategory ( . playback )
success = true
} catch let error as NSError {
categoryError = error
success = false
}
if !success {
// Handle error
}
通常可以在AppDelegate的application:didFinishLaunchingWithOptions:
方法。在某些情况下,您需要更复杂的AvauioSession配置,例如,如果您想在应用程序中的音频静音时允许听到其他应用程序的音频。在这种情况下,您可以在可以访问当前Avplayer的视图控制器中配置AvauioSession。例如:
func setUpAudioSession ( ) {
var categoryError : NSError ?
var success : Bool
do {
if let currentPlayer = currentPlayer {
// If the player is muted, then allow mixing.
// Ensure other apps can have their background audio
// active when this app is in foreground
if currentPlayer . isMuted {
try AVAudioSession . sharedInstance ( ) . setCategory ( . playback , options : . mixWithOthers )
} else {
try AVAudioSession . sharedInstance ( ) . setCategory ( . playback , options : AVAudioSession . CategoryOptions ( rawValue : 0 ) )
}
} else {
try AVAudioSession . sharedInstance ( ) . setCategory ( . playback , options : AVAudioSession . CategoryOptions ( rawValue : 0 ) )
}
success = true
} catch let error as NSError {
categoryError = error
success = false
}
if !success {
print ( " AppDelegate Debug - Error setting AVAudioSession category. Because of this, there may be no sound. ( categoryError! ) " )
}
}
示例代码可以在我们的VideoCloudBasicplayer样本项目中找到。
您可以在此处阅读有关AvauioSession的更多信息。
BrightCove Player SDK支持仅音频流,并包含一些仅音频功能。如果您为视频配置了一张海报图像,则将显示在BCOVPUIPlayerView
的contentOverlayView
中。您可以通过在BCOVPUIPlayerViewOptions
上使用contentModeForPosterImage
属性来调整海报图像视图的UIViewContentMode
,默认值是UIViewContentModeScaleAspectFit
。
您可能还希望始终保持播放器控件可见,在这种情况下,您可以在BCOVPUIPlayerViewOptions
上启用keepControlsVisible
。
如果您不想显示海报图像或只是想要更紧凑的播放视图,则可以将BCOVPUIPlayerView
的高度设置为88 pt的高度,用于紧凑(<450 pt)的布局或44 pt的高度标准布局。
如果您不使用automaticControlTypeSelection
则可以使用三个预先配置的仅视听BCOVPUIBasicControlView
布局:
basicControlViewWithAODLayout
basicControlViewWithLiveAudioLayout
basicControlViewWithLiveDVRAudioLayout
您也可以通过playbackController:playbackSession:determinedMediaType
委托法:
func playbackController ( _ controller : BCOVPlaybackController ,
playbackSession session : BCOVPlaybackSession ,
determinedMediaType mediaType : BCOVSourceMediaType ) {
switch mediaType {
case BCOVSourceMediaType . audio :
print ( " Source is Audio Only " )
case BCOVSourceMediaType . audioVideo :
print ( " Source is Audio and Video " )
default :
break
}
}
我们的VideoCloudBasicPlayer支持在锁定屏幕,控制中心和AirPlay上显示媒体信息。有关实施详细信息,请参见NowPlayingHandler
类。
视频保险杠是一个简短的资产,通常是10秒或更短的时间,它在所有其他媒体面前都播放,并且通常显示您的视频所代表的品牌或公司。玩家将像其他任何视频一样从播放API中要求保险杠,并在广告和内容之前插入。
保险杠是玩家级的功能,这意味着给定的玩家只能与单个保险杠相关联。播放列表共享相同的保险杠视频。有两种方法可以配置玩家播放保险杠视频:
bumperID
。视频的ID要查找。 // Using `bumperID`
let configuration = [
BCOVPlaybackService . ConfigurationKeyAssetID : videoID ,
BCOVPlaybackService . ConfigurationKeyBumperID : bumperID
]
// Using `bumperReferenceID`
let configuration = [
BCOVPlaybackService . ConfigurationKeyAssetID : playlistID ,
BCOVPlaybackService . ConfigurationKeyBumperReferenceID : bumperReferenceID
]
// With a Video Request
playbackService . findVideo ( withConfiguration : configuration ,
queryParameters : nil ) { ( video : BCOVVideo ? ,
jsonResponse : Any ? ,
error : Error ? ) in
...
}
// With a Playlist Request
playbackService . findPlaylist ( withConfiguration : configuration ,
queryParameters : nil ) { ( playlist : BCOVPlaylist ? ,
jsonResponse : Any ? ,
error : Error ? ) in
...
}
可以在VideoCloud/Studio的自定义字段中定义bumper_id
字段。没有先前定义的签名,可以使用bumper_id
。 bumper_id
必须是有效的视频ID。
注意:通过自定义字段( bumper_id
字段)通过的Bumperid优先于播放服务中的任何ID。
保险杠在播放时可以隐藏播放控件。
let options = BCOVPUIPlayerViewOptions ( )
options . automaticControlTypeSelection = true
options . showBumperControls = false
let playerView = BCOVPUIPlayerView ( playbackController : nil , options : options , controlsView : nil )
如果将automaticControlTypeSelection
选项”设置为true
,则保险杠的布局将适应内容(仅视频或音频)。 basicControlViewWithVODLayout
和basicControlViewWithAODLayout
布局是为保险杠, Live
或LiveDVR
布局设计的。当保险杠活动活动时,播放控件具有独特的外观:
对交互性的支持已集成到核心BrightCovePlayersDK框架中。有关与BrightCove本地播放器SDK进行交互性的完整详细信息,请参阅《交互性指南》。
如果内容包装为MP4,则可以将URL直接粘贴到大多数Web浏览器中,并且视频应播放(或下载到您的文件系统,可以在本地播放)。如果内容包装为HLS,则可以使用QuickTime播放器对其进行测试:选择File -> Open Location…
并粘贴在.m3u8
播放列表URL中,并且视频应播放。
这是一个常见的症状,即从非曼字节线中称为主要线程的Uikit或Avoundation方法。在主线程上始终调用BCOVPlaybackControllerDelegate
上的委托方法。
此消息表明默认源选择策略无法弄清楚要选择的源。默认策略选择了第一个来源,其deliveryMethod
是kBCOVSourceDeliveryHLS
(“ HLS”)。如果找不到HLS源,其后备行为将选择第一个deliveryMethod
的源为kBCOVSourceDeliveryMP4
(“ MP4”)。如果视频中没有具有“ HLS”或“ MP4”的deliveryMethod
的消息来源,则该策略将选择视频的第一个来源(无论是deliveryMethod
如何)。如果您对其选择不满意,则可以使用-[BCOVPlayerSDKManager createBasicSessionProviderWithOptions:]
并通过具有自定义sourceSelectionPolicy
属性集的BCOVBasicSessionProviderOptions
。在手动创建视频和源时,请确保使用适当的deliveryMethod
创建来源。
控制应用程序是否在iOS应用中排放音频的API是AvauioSession API。音频会话是全球应用程序的全局,这意味着其配置会影响播放器SDK创建的Avplayers发出的声音,以及应用程序可能会产生的其他声音。由于播放器SDK不知道该应用程序是如何为其他声音配置的音频会话,因此它根本不会影响音频会话。这意味着,除非您明确配置应用程序的音频会话,否则您将继承默认的行为,即在设备被静音时抑制任何和所有音频的默认行为,包括Avplayers发出的音频。为了符合Apple关于音频播放的建议,您(应用程序开发人员)必须根据您的应用程序的特定需求配置音频会话。
有关其他信息,请参见此读书中的Avaudiosession配置部分。
If you have questions, need help or want to provide feedback, please use the Support Portal or contact your Account Manager. To receive notification of new SDK software releases, subscribe to the Brightcove Native Player SDKs Google Group.