保利威文档中心

幫助中心

8 三分屏

更新時間:2023-04-17 15:27:58

8.1 概述

三分屏是一種支援 PPT 或 PDF 文件與影片同步播放的雙視窗播放模式。使用一大一小兩個播放視窗,佈局靈活,能自由切換主螢幕播放內容,支援為 PPT 或 PDF 文件的每一頁設定播放時間點來實現自動翻頁功能,支援點擊課程目錄上的課程進行播放進度跳轉,支援下載到本機離線播放。為客戶更豐富的授課場景提供了可能。

8.2 快速整合

8.2.1 SDK 版本

如果想使用點播的三分屏功能,請將 PolyvVodSDK 升級到 2.6.5 以上,Podfile 設定如下:

pod 'PolyvVodSDK', '~> 2.6.5'

8.2.2 開源程式碼

其次,大部分程式碼我們在 demo 專案的資料夾 PolyvOpenSourceModule/PPT 中提供,請把 demo 的程式碼更新到版本 2.6.5 以上,然後把這個資料夾下的程式碼拖到你的專案中。該資料夾下的檔案目錄如下:

└── PPT ├── Controller │ ├── PLVPPTBaseViewController.h │ ├── PLVPPTBaseViewController.m │ ├── PLVPPTBaseViewControllerInternal.h │ ├── PLVPPTVideoViewController.h │ ├── PLVPPTVideoViewController.m │ ├── PLVPPTViewController.h │ └── PLVPPTViewController.m └── View ├── PLVFloatingView.h ├── PLVFloatingView.m ├── PLVPPTActionView.h ├── PLVPPTActionView.m ├── PLVPPTActionViewCell.h ├── PLVPPTActionViewCell.m ├── PLVPPTControllerSkinView.h ├── PLVPPTControllerSkinView.m ├── PLVPPTFailView.h ├── PLVPPTFailView.m ├── PLVPPTLoadFailAlertView.h ├── PLVPPTLoadFailAlertView.m ├── PLVPPTSkinProgressView.h └── PLVPPTSkinProgressView.m

8.2.3 demo 範例

在 demo 專案中 Classes 路徑下,我們提供了三分屏播放頁 PLVPPTSimpleDetailController,可使用該頁面進行三分屏播放。使用程式碼如下:

PLVPPTSimpleDetailController *vctrl = [[PLVPPTSimpleDetailController alloc] init];
vctrl.vid = @"准备播放的视频 vid";
vctrl.isOffline = NO;
[self.navigationController pushViewController:vctrl animated:YES];

屬性 isOffline 預設為 NO,表示呼叫介面取得影片資源,沒有網路時即使本地有快取也無法播放,如果設定為 YES,則從本地取得影片資源,沒有網路時只要本地有快取就可以播放。

8.2.4 專案配置

由於 PPT 文件的圖片連結使用 http 協定,需要在專案的 Info.plist 檔案中的 App Transport Security Settings / Exception Domains 中增加 Key-Value 如下:

<key>doc.polyv.net</key>
  <dict>
    <key>NSExceptionAllowsInsecureHTTPLoads</key>
    <true/>
  </dict>

效果如下圖所示:

三分屏_圖1

8.3 影片播放器

8.3.1 三分屏開關

點播 SDK 中的影片播放器 PLVVodPlayerViewController 增加布林屬性 enablePPT,表示是否啟動 PPT 功能,預設為 NO,此時無論該影片有無 PPT 均不顯示。可在 PLVPPTVideoViewController.m 的方法 -player 進行設定,demo 中的程式碼如下:

- (PLVVodSkinPlayerController *)player {
    if (!_player){
        _player = [[PLVVodSkinPlayerController alloc] init];
        _player.enablePPT = YES;
        _player.enableBackgroundPlayback = YES;
        _player.autoplay = YES;
        _player.enableAd = YES;
    }
    return _player;
}

除了設定 enablePPT,還可以在此處進行播放器的其他屬性設定,譬如是否允許背景播放 enableBackgroundPlayback、是否自動播放 autoplay、是否開啟廣告 enableAd 等,更多參數詳見點播文件 4 影片播放 - 4.5 播放器配置

8.3.2 播放器皮膚

demo 中開源元件 PolyvOpenSourceModule 中提供的播放器皮膚 PLVVodPlayerSkin 新增【開/關三分屏小視窗】按鈕、全螢幕時新增【課件】按鈕。點擊【開/關三分屏小視窗】可以開啟或關閉小視窗,點擊【課件】按鈕可在全螢幕時彈出課件目錄列表。開源元件中播放器皮膚新增按鈕程式碼如下:

/// 竖屏播放器皮肤
@interface PLVVodShrinkscreenView : UIView

@property (weak, nonatomic) IBOutlet UIButton *subScreenButton; // 关闭三分屏按钮

@end
/// 全屏播放器皮肤
@interface PLVVodFullscreenView : UIView

@property (weak, nonatomic) IBOutlet UIButton *subScreenButton; // 关闭三分屏按钮
@property (weak, nonatomic) IBOutlet UIButton *pptCatalogButton; // 显示课件目录按钮

@end

按鈕的顯示與隱藏在 PLVVodPlayerSkin.m 中進行控制。只有當 enablePPT 為 YES,且播放的音/影片包含 PPT 或 PDF 文件,這兩個按鈕才會顯示。

8.3.3 播放進度回呼

PLVVodSkinPlayerController 新增播放器回呼,程式碼如下:

@interface PLVVodSkinPlayerController : PLVVodPlayerViewController

// 播放进度回调
@property (nonatomic, copy) void (^playbackTimeHandler)(NSTimeInterval currentPlaybackTime);

@end

三分屏功能將透過這個回呼,實現文件與影片播放的同步。PLVPPTBaseViewController 中的程式碼示例如下:

__weak typeof(self) weakSelf = self;
self.videoController.player.playbackTimeHandler = ^(NSTimeInterval currentPlaybackTime) {
      [weakSelf.pptController playAtCurrentSecond:(int)currentPlaybackTime];
};

其中,self.videoController.player 為 PLVVodSkinPlayerController 的實例,weakSelf.pptController 為下文即將提到的 PPT 播放器。

8.3.4 播放器容器

PLVPPTVideoViewController 是播放器的檢視容器,用於配置影片播放器、控制播放器皮膚、影片播放業務邏輯程式碼等,PLVPPTBaseViewController 中的程式碼示例如下:

#import "PLVPPTBaseViewController.h"
#import "PLVPPTVideoViewController.h"
#import <PLVVodSDK/PLVVodSDK.h>

@interface PLVPPTBaseViewController ()<
PLVPPTVideoViewControllerProtocol
>

@property (nonatomic, strong) UIView *mainView; // 大屏视图
@property (nonatomic, strong) PLVPPTVideoViewController *videoController;

@end

@implementation PLVPPTBaseViewController

#pragma mark - Life Cycle
  
- (void)viewDidLoad {
    [super viewDidLoad];
    [self.view addSubview:self.mainView];
    [self.mainView addSubview:self.videoController.view]; // 添加播放器视图到大屏视图
}

- (void)dealloc{
    _videoController.delegate = nil;
}

#pragma mark - Getter & Setter

- (PLVPPTVideoViewController *)videoController {
    if (!_videoController){
        _videoController = [[PLVPPTVideoViewController alloc] init];
        _videoController.delegate = self;
    }
    return _videoController;
}

#pragma mark - PLVPPTVideoViewControllerProtocol

- (void)videoWithVid:(NSString *)vid title:(NSString *)title hasPPT:(BOOL)hasPPT localPlay:(BOOL)localPlay {
// 视频播放回调,获取到视频资源后调用
// vid:当前播放视频的 vid
// title:当前播放视频的标题
// hasPPT:当前播放视频是否包含文档
// localPlay:播放资源是否为本地缓存,YES 为是,NO 为否
}

- (PLVVodPlaybackMode)currenPlaybackMode {
// 当前播放音视频模式:
// PLVVodPlaybackModeDefault
// PLVVodPlaybackModeVideo
// PLVVodPlaybackModeAudio
}

@end

「8.3.2 播放器皮膚」一節中提到的新增按鈕的響應事件,也可以在 PLVPPTBaseViewController.m 中進行設定:

- (PLVPPTVideoViewController *)videoController {
    if (!_videoController){
        _videoController = [[PLVPPTVideoViewController alloc] init];
        _videoController.delegate = self;
        
        __weak typeof(self) weakSelf = self;
        _videoController.closeSubscreenButtonActionHandler = ^{
            // 打开/关闭小屏
        };
        _videoController.pptCatalogButtonActionHandler = ^{
            // 打开课件列表
        };
    }
    return _videoController;
}

8.4 PPT 播放器

demo 中的開源元件 PolyvOpenSourceModule 提供了 PPT 播放器 PLVPPTViewController 用於播放 PPT 或 PDF 文件,並支援後台自訂文件翻頁的時間點,實現文件與影片同步播放。

8.4.1 PPT 載入

PPT 播放器簡單使用示例如下:

self.pptController = [[PLVPPTViewController alloc] init];
self.pptController.ppt = ppt;

其中屬性 pptPLVVodPPT 模型,表示一個文件資料模型。使用 PLVVodPPT 的以下方法取得 PPT 文件線上資料(離線資料的取得見 8.7):

// 获取在线数据
+ (void)requestPPTWithVid:(NSString *)vid completion:(void (^)(PLVVodPPT * _Nullable ppt, NSError * _Nullable error))completion;

PLVPPTBaseViewController.m 的程式碼示例如下:

- (void)getPPTJson {
    [PLVVodPPT requestPPTWithVid:self.vid completion:^(PLVVodPPT * _Nullable ppt, NSError * _Nullable error) {
        if (error == nil && ppt) {
            // 获取 ppt 数据成功
        } else {
            // 获取 ppt 数据失败
        }
    }];
}

8.4.2 PPT 翻頁

PPT 播放器提供了以下兩個方法,實現文件的翻頁:

@interface PLVPPTViewController : UIViewController

 /**
 将文档切换到特定播放时间点的特定页
 @param second 当前视频播放时间点,单位:秒
 */
- (void)playAtCurrentSecond:(NSInteger)second;

/**
 将文档切换到特定页
 @param index 文档的第 index 页
 */
- (void)playPPTAtIndex:(NSInteger)index;

@end

PLVPPTBaseViewController 中,方法 -playAtCurrentSecond: 在影片播放進度回呼中呼叫,實現與影片播放的同步。方法 -playPPTAtIndex: 用於手動選擇播放某一頁文件時呼叫。

8.4.3 PPT 播放器皮膚

PPT 播放器 PLVPPTViewController 提供了簡單的皮膚,一個是載入失敗時的文字顯示「暫無課件」,一個是載入中的 loading 控制項,還有一個是下載課件時的下載進度控制項。這幾個皮膚可透過以下四個方法進行控制:

@interface PLVPPTViewController (PLVPPTSkin)

/**
 开始加载 ppt
 */
- (void)startLoading;

 /**
 加载 ppt 失败
 */
- (void)loadPPTFail;

/**
 开始下载 ppt
 */
- (void)startDownloading;

/**
 下载 ppt 进度变化
 @param progress ppt 下载进度
 */
- (void)setDownloadProgress:(CGFloat)progress;

@end

載入/下載 PPT 成功時,即 PPT 屬性被賦值(非 nil)時,這些控制項會自動隱藏,無需呼叫任何介面。

8.5 三分屏小視窗

demo 中的開源元件 PolyvOpenSourceModule 提供了自訂 UIView 的子類別 PLVFloatingView 作為三分屏播放時的(懸浮)小視窗。

小視窗大小固定,由類別方法 +viewSize 定義:

+ (CGSize)viewSize {
    return CGSizeMake(125, 70);
}

提供協定 PLVFloatingViewProtocol 和代理方法 -tapAtFloatingView: 用於響應視窗點擊事件:

@protocol PLVFloatingViewProtocol <NSObject>

- (void)tapAtFloatingView:(PLVFloatingView *)floatingView;

@end

三分屏小視窗 PLVFloatingView 支援透過手勢拖曳改變視窗位置,如果想固定位置,只需將 PLVFloatingView.m 檔案中的以下幾行程式碼註解掉即可:

@implementation PLVFloatingView
  
  - (instancetype)init {
    self = [super init];
    if (self) {
      
      ……
        
      // 如果想固定窗口,注释掉下面这两行代码  
      UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGestureRecognizer:)];
      [self addGestureRecognizer:panGestureRecognizer];
    }
    return self;
}

@end

8.6 三分屏播放頁

demo 中的開源元件 PolyvOpenSourceModule 提供了 PLVPPTBaseViewController 作為三分屏播放頁。

PLVPPTBaseViewController 提供對外屬性 vidisOfflineplaybackMode

@interface PLVPPTBaseViewController : UIViewController

/**  
 播放视频的 vid
 */
@property (nonatomic, copy) NSString *vid;

/**
  是否离线播放,默认为 NO
 YES: 从本地获取视频资源,没有网络时只要本地有缓存就可以播放
 NO: 调用接口获取视频资源,没有网络时即使本地有缓存也无法播放
 */
@property (nonatomic, assign) BOOL isOffline;

/**
  播放模式:默认、视频、音频三种
 在线播放时会自动设置播放模式
 离线时需根据本地资源类型手动设置播放模式
 */
@property (nonatomic, assign) PLVVodPlaybackMode playbackMode;

@end

demo 中的 PLVPPTSimpleDetailControllerPLVPPTBaseViewController 的子類別,三分屏等業務邏輯程式碼都封裝在父類別中,使用 PLVPPTSimpleDetailController 進行影片播放的程式碼示例如下:

PLVPPTSimpleDetailController *vctrl = [[PLVPPTSimpleDetailController alloc] init];
vctrl.vid = vid;
[self.navigationController pushViewController:vctrl animated:YES];

PLVPPTBaseViewController 還提供了以下幾個空方法,供子類別覆寫:

// 获取课件异常时,会执行这个方法,子类需要时可覆写
- (void)getPPTFail;

// ppt 的值更新时,获得 ppt 模型,或者置 nil 会执行这个方法,子类需要时可覆写
- (void)getPPTSuccess;

// 横竖屏切换时会执行这个方法,子类需要时可覆写
- (void)interfaceOrientationDidChange;

檔案 PLVPPTBaseViewControllerInternal.h 定義了子類別可見的其他屬性跟方法。

8.7 下載器

SDK 2.6.5 之後的下載器 PLVVodDownloadManager 支援三分屏模式的影片、文件打包下載。呼叫方法不變:

PLVVodVideo *video;
[[PLVVodDownloadManager sharedManager] downloadVideo:video];

影片模型 PLVVodVideo 新增屬性 hasPPTppt_linkPLVVodDownloadManager 會在下載影片時,根據該屬性判斷是否需要下載 PPT 文件,從屬性 ppt_link 取得文件的下載連結。

下載器 PLVVodDownloadManager 新增 PPT 下載介面 -downloadPPTWithVideo:completion:

/**
 下载PPT 文件
 @param video PLVVodVideo 视频对象
 */
- (void)downloadPPTWithVideo:(PLVVodVideo *)video completion:(void(^)(PLVVodDownloadInfo *info))completion;

可透過這個介面單獨下載某個影片對應的 PPT。

下載成功後,透過類別 PLVVodPPT 提供的方法 -requestCachePPTWithVid:completion: 取得離線 PPT 文件資料:

+ (void)requestCachePPTWithVid:(NSString *)vid completion:(void (^)(PLVVodPPT * _Nullable ppt, NSError * _Nullable error))completion;

PLVPPTBaseViewController.m 還提供了 PPT 的下載進度回呼、下載狀態變化回呼範例,範例程式碼如下:

@implementation PLVPPTBaseViewController (PPT)
  
- (void)downloadPPT {
    PLVVodVideo *video = self.video;
    [[PLVVodDownloadManager sharedManager] downloadPPTWithVideo:video completion:^(PLVVodDownloadInfo *info) {
        [self handlePPTDownload:info];
    }];
}

- (void)handlePPTDownload:(PLVVodDownloadInfo *)info {
    __weak typeof(self) weakSelf = self;
    PLVVodDownloadInfo *downloadInfo = info;
    downloadInfo.progressDidChangeBlock = ^(PLVVodDownloadInfo *info) {
        NSLog(@"下载进度:%f", info.progress);
    };
    
    downloadInfo.stateDidChangeBlock = ^(PLVVodDownloadInfo *info) {
        if (info.state == PLVVodDownloadStateSuccess) {
          NSLog(@"下载成功");
        } else if (info.state == PLVVodDownloadStateFailed) {
          NSLog(@"下载失败");
        }
    };
}

@end
联系客服,在线咨询