Browse Source

添加播放器

jsonwang 3 years ago
parent
commit
e1e691ab15

+ 3 - 1
BFFramework.podspec

@@ -64,6 +64,8 @@ TODO: Add long description of the pod here.
 
     s.dependency 'Bugly','2.5.71' # 奔溃分析组件
 
+    s.dependency 'TXLiteAVSDK_Player','8.4.9944' # 腾讯播放器组件
+
     s.dependency "NXFramework-Swift"
-    # s.dependency 'KingfisherWebP','0.4.2' # 加载WebP格式图片库 使用https://github.com/webmproject/libwebp.git地址可以不翻
+    s.dependency 'KingfisherWebP','0.4.2' # 加载WebP格式图片库 使用https://github.com/webmproject/libwebp.git地址可以不翻
 end

+ 2 - 0
BFFramework/Classes/BFFramework_custom_umbrella.h

@@ -18,4 +18,6 @@
 #import "FBShimmeringView.h"
 #import "UIControl+NXCategory.h"
 
+#import <TXLiteAVSDK_Player/TXLiteAVSDK.h>
+
 #endif /* AliyunOSSiOS_Bridging_Header */

+ 238 - 0
BFFramework/Classes/Utils/PQSingletoVideoPlayer.swift

@@ -0,0 +1,238 @@
+
+//
+//  PQVideoPlayer.swift
+//  PQSpeed
+//
+//  Created by SanW on 2020/6/3.
+//  Copyright © 2020 BytesFlow. All rights reserved.
+//
+
+import UIKit
+
+public class PQSingletoVideoPlayer: NSObject {
+    static public let shared = PQSingletoVideoPlayer()
+    public var isPlayEnd: Bool = false // 是否已播放完成
+    var isRealPlay: Bool = false // 是否已真实播放
+    var isSemiRealPlay: Bool = false // 是否已播放到十秒
+    var isPlayBegin: Bool = false // 是否已缓冲完成开始播放
+    var isFirstFrame: Bool = false // 是否已显示第一帧加载完成
+    var isPlayerError: Bool = false // 是否播放失败
+    var loadingTime: TimeInterval = 0 // 加载时长
+
+    var playId: String = getUniqueId(desc: "playId") // 播放ID
+    /// 进度回调
+    var progressBloc: ((_ loadProgress: Float, _ playProgress: Float, _ duration: Float) -> Void)?
+    /// 播放状态回调
+    public var playStatusBloc: ((_ playStatus: PQVIDEO_PLAY_STATUS) -> Void)?
+    public var playControllerView: UIView?
+    public var playVideoData: PQVideoListModel?
+
+    lazy public var player: TXVodPlayer = {
+        let player = TXVodPlayer()
+        let config = TXVodPlayConfig()
+        config.cacheFolderPath = videoCacheDirectory
+        config.maxCacheItems = 5
+        player.config = config
+        player.vodDelegate = self
+        player.setRenderMode(.RENDER_MODE_FILL_EDGE)
+        return player
+    }()
+
+    public func configPlyer(videoData: PQVideoListModel, controllerView: UIView) {
+        isPlayEnd = false
+        isRealPlay = false
+        isSemiRealPlay = false
+        isPlayBegin = false
+        isFirstFrame = false
+        isPlayerError = false
+        loadingTime = Date().timeIntervalSince1970 * 1000
+
+        player.stopPlay()
+        player.removeVideoWidget()
+
+        player.setupVideoWidget(controllerView, insert: 0)
+        player.enableHWAcceleration = true
+        playControllerView = controllerView
+        playVideoData = videoData
+        if playVideoData!.playProgress >= 0.0 {
+            //
+            var progress: CGFloat = playVideoData!.playProgress
+            if progress > 5.0, progress < 20 {
+                progress = progress - 5.0
+                if progress <= 0 {
+                    progress = 0
+                }
+            }
+            BFLog(message: "xxx.playProgress =\(playVideoData!.playProgress),\(progress)")
+            player.setStartTime(progress)
+        }
+        playId = getUniqueId(desc: "playId")
+        BFLog(message: "\(String(describing: videoData.title)) 开始播放 \(videoData.videoPath ?? "")")
+        player.startPlay(videoData.videoPath)
+         
+        if PQSingletoMemoryUtil.shared.playCount < 4 {
+            PQSingletoMemoryUtil.shared.playCount = PQSingletoMemoryUtil.shared.playCount + 1
+        }
+    }
+
+    func resetPlayer() {
+        if (playControllerView != nil) {
+            player.removeVideoWidget()
+            player.setupVideoWidget(playControllerView, insert: 0)
+            if playVideoData!.playProgress >= 0.0 {
+                //
+                var progress: CGFloat = playVideoData!.playProgress
+                if progress > 5.0, progress < 20 {
+                    progress = progress - 5.0
+                    if progress <= 0 {
+                        progress = 0
+                    }
+                }
+                BFLog(message: "xxx.playProgress =\(playVideoData!.playProgress),\(progress)")
+                player.setStartTime(progress)
+            }
+            playId = getUniqueId(desc: "playId")
+            player.startPlay(playVideoData!.videoPath)
+           
+        }
+    }
+
+    public func stopPlayer(isRemove: Bool = true) {
+        player.stopPlay()
+        if isRemove {
+            player.removeVideoWidget()
+            playControllerView = nil
+            playVideoData = nil
+        }
+    }
+
+    override private init() {
+        super.init()
+    }
+
+    override public func copy() -> Any {
+        return self
+    }
+
+    override public func mutableCopy() -> Any {
+        return self
+    }
+}
+
+extension PQSingletoVideoPlayer: TXVodPlayListener {
+    /// 播放进度回调
+    /// - Parameters:
+    ///   - player: <#player description#>
+    ///   - EvtID: <#EvtID description#>
+    ///   - param: <#param description#>
+    public func onPlayEvent(_ player: TXVodPlayer!, event EvtID: Int32, withParam param: [AnyHashable: Any]!) {
+        switch EvtID {
+        case PLAY_EVT_PLAY_PROGRESS.rawValue: // 播放进度
+            // 加载进度, 单位是秒
+            let loadProgress: Float = param[EVT_PLAYABLE_DURATION] as! Float
+            // 播放进度, 单位是秒
+            let playProgress: Float = param[EVT_PLAY_PROGRESS] as! Float
+            // 总长度, 单位是秒
+            let duration: Float = param[EVT_PLAY_DURATION] as! Float
+            if player.currentPlaybackTime() >= 10.0, player.currentPlaybackTime() <= 10.1 {
+                // 10.0上报
+                if !isSemiRealPlay, playVideoData != nil {
+                    isSemiRealPlay = true
+                    // 播放上报
+                    PQEventTrackViewModel.videoRelationReportUpload(reportLogType: .reportLogType_Action, videoData: playVideoData, pageSource: nil, businessType: .bt_videoSemiRealPlay, objectType: nil, extParams: nil, shareId: nil, videoIds: nil, playId: playId)
+                }
+            }
+            if player.currentPlaybackTime() >= 20.0 || ((playProgress / duration) >= 0.3) {
+                // 视频播放到20s或播放到总时长30%,哪个先到为准
+                if !isRealPlay, playVideoData != nil {
+                    isRealPlay = true
+                    // 播放上报
+                    PQEventTrackViewModel.videoRelationReportUpload(reportLogType: .reportLogType_realPlay, videoData: playVideoData, pageSource: nil, businessType: .bt_videoRealPlay, objectType: nil, extParams: nil, shareId: nil, videoIds: nil, playId: playId)
+                }
+            }
+            if progressBloc != nil {
+                progressBloc!(loadProgress, playProgress, duration)
+            }
+        case PLAY_EVT_RCV_FIRST_I_FRAME.rawValue:
+            // 首帧完成开始播放
+            if !isPlayBegin, playVideoData != nil {
+                isPlayBegin = true
+                // 播放上报
+                PQEventTrackViewModel.videoRelationReportUpload(reportLogType: .reportLogType_Action, videoData: playVideoData, pageSource: nil, businessType: .bt_videoPlaySuccess, objectType: nil, extParams: nil, shareId: nil, videoIds: nil, playId: playId)
+            }
+
+        case PLAY_EVT_PLAY_LOADING.rawValue: // 视频播放loading
+            if playStatusBloc != nil {
+                playStatusBloc!(.PQVIDEO_PLAY_STATUS_LOADING)
+            }
+        case PLAY_EVT_PLAY_BEGIN.rawValue: // 开始播放
+            if playStatusBloc != nil {
+                playStatusBloc!(.PQVIDEO_PLAY_STATUS_BEGIN)
+            }
+            // 首帧加载完成
+            if !isFirstFrame, playVideoData != nil {
+                isFirstFrame = true
+                // 播放上报
+                PQEventTrackViewModel.videoRelationReportUpload(reportLogType: .reportLogType_play, videoData: playVideoData, pageSource: nil, businessType: nil, objectType: nil, extParams: nil, shareId: nil, videoIds: nil, playId: playId)
+                let duration = Int((Date().timeIntervalSince1970 * 1000) - loadingTime)
+                BFLog(message: "加载时长:\(duration)")
+                // 加载时间上报
+                PQEventTrackViewModel.videoRelationReportUpload(reportLogType: .reportLogType_Frontend, videoData: playVideoData, pageSource: nil, businessType: .bt_videoPlaySuccessTime, objectType: nil, extParams: ["duration": duration, "proxyEnable": "0", "url": playVideoData?.videoPath ?? "", "videoId": playVideoData?.uniqueId ?? "0"], shareId: nil, videoIds: nil, playId: playId)
+            }
+            BFLog(message: "首帧加载完成")
+        case PLAY_EVT_PLAY_END.rawValue: // 播放结束
+            player.pause()
+            playId = getUniqueId(desc: "playId")
+            if playStatusBloc != nil {
+                playStatusBloc!(.PQVIDEO_PLAY_STATUS_END)
+            }
+            if !isPlayEnd, playVideoData != nil {
+                isPlayEnd = true
+                // 播放结束上报
+                PQEventTrackViewModel.videoRelationReportUpload(reportLogType: .reportLogType_Action, videoData: playVideoData, pageSource: nil, businessType: .bt_videoPlayEnd, objectType: nil, extParams: nil, shareId: nil, videoIds: nil, playId: playId)
+            }
+        case PLAY_ERR_NET_DISCONNECT.rawValue: // 重连失败
+            if playStatusBloc != nil {
+                playStatusBloc!(.PQVIDEO_PLAY_STATUS_DISCONNECT)
+            }
+            if !isPlayerError, playVideoData != nil {
+                isPlayerError = true
+                // 播放失败
+                PQEventTrackViewModel.videoRelationReportUpload(reportLogType: .reportLogType_Frontend, videoData: playVideoData, pageSource: nil, businessType: .bt_videoPlayError, objectType: nil, extParams: ["pageSource": playVideoData!.pageSource.rawValue, "networkType": networkStatus(), "extra": "0", "hasRetry": true, "url": playVideoData?.videoPath ?? "", "videoId": playVideoData?.uniqueId ?? "0", "what": EvtID], shareId: nil, videoIds: nil, playId: playId)
+            }
+        case PLAY_ERR_FILE_NOT_FOUND.rawValue: // 播放文件不存在
+            if playStatusBloc != nil {
+                playStatusBloc!(.PQVIDEO_PLAY_STATUS_NOT_FOUND)
+            }
+            if !isPlayerError, playVideoData != nil {
+                isPlayerError = true
+                // 播放失败
+                PQEventTrackViewModel.videoRelationReportUpload(reportLogType: .reportLogType_Frontend, videoData: playVideoData, pageSource: nil, businessType: .bt_videoPlayError, objectType: nil, extParams: ["pageSource": playVideoData!.pageSource.rawValue, "networkType": networkStatus(), "extra": "0", "hasRetry": false, "url": playVideoData?.videoPath ?? "", "videoId": playVideoData?.uniqueId ?? "0", "what": EvtID], shareId: nil, videoIds: nil, playId: playId)
+            }
+        case PLAY_ERR_HEVC_DECODE_FAIL.rawValue, PLAY_ERR_HLS_KEY.rawValue, PLAY_ERR_GET_PLAYINFO_FAIL.rawValue, PLAY_WARNING_VIDEO_DECODE_FAIL.rawValue, PLAY_WARNING_AUDIO_DECODE_FAIL.rawValue: // H265解码失败,HLS解码key获取失败,获取点播文件信息失败,当前视频解码失败,当前音频解码失败
+
+            if !isPlayerError, playVideoData != nil {
+                isPlayerError = true
+                // 播放失败
+                PQEventTrackViewModel.videoRelationReportUpload(reportLogType: .reportLogType_Frontend, videoData: playVideoData, pageSource: nil, businessType: .bt_videoPlayError, objectType: nil, extParams: ["pageSource": playVideoData!.pageSource.rawValue, "networkType": networkStatus(), "extra": "0", "hasRetry": false, "url": playVideoData?.videoPath ?? "", "videoId": playVideoData?.uniqueId ?? "0", "what": EvtID], shareId: nil, videoIds: nil, playId: playId)
+            }
+        case PLAY_WARNING_RECONNECT.rawValue: // 断线重连已启动重新连接
+            if playStatusBloc != nil {
+                playStatusBloc!(.PQVIDEO_PLAY_STATUS_RECONNECT)
+            }
+        case PLAY_WARNING_RECV_DATA_LAG.rawValue, PLAY_WARNING_VIDEO_PLAY_LAG.rawValue: // 网络来包不稳:可能是下行带宽不足 | 当前视频播放出现卡顿(用户直观感受)
+            // 播放失败
+            PQEventTrackViewModel.videoRelationReportUpload(reportLogType: .reportLogType_Frontend, videoData: playVideoData, pageSource: nil, businessType: .bt_videoPlaySlow, objectType: nil, extParams: ["pageSource": playVideoData!.pageSource.rawValue, "networkType": networkStatus(), "url": playVideoData?.videoPath ?? "", "videoId": playVideoData?.uniqueId ?? "0", "what": EvtID, "position": player.currentPlaybackTime()], shareId: nil, videoIds: nil, playId: playId)
+        default:
+            break
+        }
+    }
+
+    /// 网络状态回调
+    /// - Parameters:
+    ///   - player: <#player description#>
+    ///   - param: <#param description#>
+    public func onNetStatus(_: TXVodPlayer!, withParam _: [AnyHashable: Any]!) {
+        // BFLog(message: "onNetStatus:\(param)")
+    }
+}