videoPlayViewController~.m 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. //
  2. // videoPlayViewController.m
  3. // 双子星云手机
  4. //
  5. // Created by xd h on 2024/5/21.
  6. //
  7. #import "videoPlayViewController.h"
  8. #import <WebKit/WebKit.h>
  9. #import <AVFoundation/AVFoundation.h>
  10. @interface videoPlayViewController ()<WKUIDelegate,WKNavigationDelegate,WKScriptMessageHandler>
  11. @property (nonatomic, strong) WKWebView *curWKWebView;
  12. @property (nonatomic, strong)AVPlayer*player;
  13. @end
  14. @implementation videoPlayViewController
  15. - (void)viewDidLoad {
  16. [super viewDidLoad];
  17. // Do any additional setup after loading the view.
  18. [self.toolBar setHidden:YES];
  19. [self.navigationBar setHidden:YES];
  20. [self.navBarBGView setHidden:NO];
  21. //self.navBarBGView.backgroundColor = [UIColor whiteColor];
  22. [self.view setBackgroundColor:[UIColor whiteColor]];
  23. //[self setUpVideoPlayer];
  24. }
  25. #pragma mark ---播放器
  26. - (void)setUpVideoPlayer {
  27. //创建网页配置对象
  28. WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
  29. // 是使用h5的视频播放器在线播放, 还是使用原生播放器全屏播放
  30. //config.allowsInlineMediaPlayback = YES;
  31. //设置视频是否需要用户手动播放 设置为NO则会允许自动播放
  32. config.mediaTypesRequiringUserActionForPlayback = NO;
  33. //设置是否允许画中画技术 在特定设备上有效
  34. config.allowsPictureInPictureMediaPlayback = NO;
  35. //设置请求的User-Agent信息中应用程序名称 iOS9后可用
  36. //config.applicationNameForUserAgent = @"ChinaDailyForiPad";
  37. //自定义的WKScriptMessageHandler 是为了解决内存不释放的问题
  38. // WeakWebViewScriptMessageDelegate *weakScriptMessageDelegate = [[WeakWebViewScriptMessageDelegate alloc] initWithDelegate:self];
  39. //这个类主要用来做native与JavaScript的交互管理
  40. // 注入js 解决进入播放就横屏问题
  41. WKUserContentController *content = [[WKUserContentController alloc]init];
  42. //1解决解决进入播放就横屏问题
  43. NSString *jSString = @"document.getElementsByTagName('video')[0].setAttribute('playsinline','playsinline');";
  44. WKUserScript *wkUserScript = [[WKUserScript alloc] initWithSource:jSString injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
  45. [content addUserScript:wkUserScript];
  46. //2,暂停播放监听
  47. NSString *PausePlayListenerjSString = @"document.getElementsByTagName('video')[0].addEventListener('pause', function(e) {window.webkit.messageHandlers.pause.postMessage(\"pause\");})";
  48. WKUserScript *PausePlayListenerwkUScript = [[WKUserScript alloc] initWithSource:PausePlayListenerjSString injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
  49. [content addUserScript:PausePlayListenerwkUScript];
  50. //3,继续播放监听
  51. NSString *ContinuePlayingListenerjSString = @"document.getElementsByTagName('video')[0].addEventListener('play', function(e) {window.webkit.messageHandlers.play.postMessage(\"play\");})";
  52. WKUserScript *ContinuePlayingListenerwkUScript = [[WKUserScript alloc] initWithSource:ContinuePlayingListenerjSString injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
  53. [content addUserScript:ContinuePlayingListenerwkUScript];
  54. //4,播放结束监听
  55. NSString *EndOfPlayListenerjSString = @"document.getElementsByTagName('video')[0].addEventListener('ended', function(e) {window.webkit.messageHandlers.ended.postMessage(\"ended\");})";
  56. WKUserScript *EndOfPlayListenerwkUScript = [[WKUserScript alloc] initWithSource:EndOfPlayListenerjSString injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
  57. [content addUserScript:EndOfPlayListenerwkUScript];
  58. //添加一个协议
  59. [content addScriptMessageHandler:self name:@"play"];
  60. [content addScriptMessageHandler:self name:@"pause"];
  61. [content addScriptMessageHandler:self name:@"ended"];
  62. //5,暂停播放播放
  63. NSString *pauseJS = @"var videos = document.getElementsByTagName(\"video\");\
  64. function pauseVideo(){videos[0].pause();}\
  65. function playVideo(){videos[0].play();}";
  66. WKUserScript *PausePlaywkUScript = [[WKUserScript alloc] initWithSource:pauseJS injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
  67. [content addUserScript:PausePlaywkUScript];
  68. config.userContentController= content;
  69. _curWKWebView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_W, SCREEN_H) configuration:config];
  70. // UI代理
  71. _curWKWebView.UIDelegate = self;
  72. // 导航代理
  73. _curWKWebView.navigationDelegate = self;
  74. [self.view addSubview:_curWKWebView];
  75. }
  76. - (void)viewWillAppear:(BOOL)animated
  77. {
  78. [super viewWillAppear:animated];
  79. [self beginPlayVideoFun];
  80. }
  81. - (void)beginPlayVideoFun
  82. {
  83. NSString *filePath = _VideoDataMode.path;
  84. NSString *urlStr = ksharedAppDelegate.NASFileByBoxService;
  85. NSString *fileUrl = [[NSString alloc] initWithFormat:@"%@getFile?path=%@",urlStr,filePath];
  86. fileUrl = [fileUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
  87. //fileUrl = @"http://transfer.armclouding.com:10010/getFile?path=/storage/006A-A69C/bf0308/Screenrecording_20231101_163026.mp4";
  88. fileUrl = @"http://transfertest.armclouding.com:10010/getFile?path=/sdcard/bb.mp4";
  89. NSURL * sourceMovieURL= [NSURL URLWithString:fileUrl];
  90. // 根据URL创建请求
  91. // NSURLRequest *request = [NSURLRequest requestWithURL:sourceMovieURL];
  92. // [_curWKWebView loadRequest:request];
  93. //111111111
  94. NSURL *videoUrl = sourceMovieURL;
  95. AVAsset *asset = [AVAsset assetWithURL:videoUrl];
  96. AVPlayerItem*videoItem = [AVPlayerItem playerItemWithAsset:asset]; // 视频资源信息 M
  97. _player = [AVPlayer playerWithPlayerItem:videoItem]; // 视频控制播放层 C
  98. AVPlayerLayer*playerLayer = [[AVPlayerLayer alloc]init]; // 视频展示层 V
  99. playerLayer.player = _player;
  100. playerLayer.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height);
  101. [self.view.layer addSublayer:playerLayer]; // 添加到父视图的layer层
  102. // 监听视频状态
  103. [videoItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:@"item.status"];
  104. // 监听缓冲进度
  105. [videoItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:@"item.loaded"];
  106. //获取播放进度
  107. [_player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
  108. float startSeconds = CMTimeGetSeconds(time); // 已经播放的秒数
  109. HLog(@"22222 %f",startSeconds);
  110. }];
  111. // 接收播放完成通知
  112. //[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handlePlayEnd) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
  113. }
  114. #pragma mark 事件代理
  115. // 页面开始加载时调用
  116. -(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
  117. }
  118. // 当内容开始返回时调用
  119. - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{
  120. }
  121. // 页面加载完成之后调用
  122. - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{//这里修改导航栏的标题,动态改变
  123. }
  124. // 页面加载失败时调用
  125. - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation{
  126. }
  127. // 接收到服务器跳转请求之后再执行
  128. - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{
  129. }
  130. // 在收到响应后,决定是否跳转
  131. - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
  132. HLog(@"%@",webView);
  133. HLog(@"%@",navigationResponse);
  134. WKNavigationResponsePolicy actionPolicy = WKNavigationResponsePolicyAllow;
  135. //这句是必须加上的,不然会异常
  136. decisionHandler(actionPolicy);
  137. }
  138. // 在发送请求之前,决定是否跳转
  139. - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
  140. HLog(@"URL=======%@", navigationAction.request.URL);
  141. HLog(@"URL.scheme=======%@", navigationAction.request.URL.scheme);
  142. WKNavigationActionPolicy actionPolicy = WKNavigationActionPolicyAllow;
  143. if (navigationAction.targetFrame == nil) {
  144. [webView loadRequest:navigationAction.request];
  145. }
  146. if (navigationAction.navigationType==WKNavigationTypeBackForward) {//判断是返回类型
  147. }
  148. //这句是必须加上的,不然会异常
  149. decisionHandler(actionPolicy);
  150. //NSString *url = navigationAction.request.URL.absoluteString;
  151. }
  152. #pragma mark - WKScriptMessageHandler
  153. - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
  154. HLog(@"%@",NSStringFromSelector(_cmd));
  155. HLog(@"%@",message);
  156. HLog(@"%@",message.body);
  157. HLog(@"%@",message.name);
  158. NSString *jsonStr = message.body; //
  159. HLog(@"%@",jsonStr);
  160. KWeakSelf
  161. if ([message.name caseInsensitiveCompare:@"play"] == NSOrderedSame) {
  162. NSLog(@"video is play");
  163. }
  164. else if ([message.name caseInsensitiveCompare:@"pause"] == NSOrderedSame) {
  165. NSLog(@"video is pause");
  166. }
  167. else if ([message.name caseInsensitiveCompare:@"ended"] == NSOrderedSame) {
  168. NSLog(@"video is ended");
  169. [weakSelf playVideo];
  170. }
  171. }
  172. #pragma mark 原生调用JS暂停
  173. - (void)pausePlay
  174. {
  175. [_curWKWebView evaluateJavaScript:@"pauseVideo()" completionHandler:^(id _Nullable response, NSError * _Nullable error) {
  176. NSLog(@"response:%@,error:%@",response,error);
  177. }];
  178. }
  179. - (void)playVideo
  180. {
  181. [_curWKWebView evaluateJavaScript:@"playVideo()" completionHandler:^(id _Nullable response, NSError * _Nullable error) {
  182. NSLog(@"response:%@,error:%@",response,error);
  183. }];
  184. }
  185. //通过KVO来观察status属性的变化,来获得播放之前的错误信息
  186. - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
  187. {
  188. if ([keyPath isEqualToString:@"status"]) {
  189. AVPlayerStatus status = [change[NSKeyValueChangeNewKey] intValue];
  190. switch (status) {
  191. case AVPlayerStatusFailed:
  192. {
  193. NSError *error = self.player.currentItem.error;
  194. NSLog(@"url有误:%@",error);
  195. }
  196. break;
  197. case AVPlayerStatusReadyToPlay:
  198. {
  199. NSLog(@"准备好播放了");
  200. }
  201. break;
  202. case AVPlayerStatusUnknown:
  203. {
  204. NSLog(@"视频资源出现未知错误");
  205. }
  206. break;
  207. default:
  208. break;
  209. }
  210. }
  211. }
  212. @end