最近遇到奇葩问题,苹果手机公众号和h5网页中视频无法播放,在网络中找寻了好多解决方案,但还是没能彻底解决。

出现这个问题网上反馈多数因为两个情况,一、视频输出流问题;二、视频格式问题;围绕这两个点展开处理。

首先解决视频流输出问题,本次项目采用的java,springboot方式,项目默认结构为文件存储服务器本地,通过转换读取方式,直接访问文件地址即可获取。之后再网上找寻了很多输出视频流方式的例子;

这里将我们使用的例子代码贴出,仅供参考,具体可根据项目需求调整;其核心的断点流传输工具类可不同改动。

fileUpload.path: D:/fileUpload/
fileServic.path: http://192.168.2.198:8069/filestatic/

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;@Slf4j
@RestController
public class CommonController {/*** 请求访问域名地址*/@Value("${fileServic.path}")private String fileServicPath;/*** 文件存储物理路径*/@Value("${fileUpload.path}")private String fileUploadPath;/*** 获取视频** @param request* @param response*/@GetMapping("/filestatic/{date}/{fileName}")public void getPlayResource(HttpServletRequest request, HttpServletResponse response,@PathVariable(name = "date") String date,@PathVariable(name = "fileName") String fileName) {String rangeString = request.getHeader(HttpHeaders.RANGE);log.info("RANGE================,{}", rangeString);fileName = fileUploadPath + "/" + date + "/" + fileName;if (StringUtils.isNotEmpty(fileName)) {if (fileName.indexOf("mp4") > -1) {play(fileName,request,response);} else {try {writeBytes(fileName, response.getOutputStream());} catch (IOException e) {log.error("下载文件失败", e);}}}}/*** 非视频类文件预览加载** @param filePath* @param os* @throws IOException*/public void writeBytes(String filePath, OutputStream os) throws IOException {FileInputStream fis = null;try {File file = new File(filePath);if (!file.exists()) {throw new FileNotFoundException(filePath);}fis = new FileInputStream(file);byte[] b = new byte[1024];int length;while ((length = fis.read(b)) > 0) {os.write(b, 0, length);}} catch (IOException e) {throw e;} finally {if (os != null) {try {os.close();} catch (IOException e1) {e1.printStackTrace();}}if (fis != null) {try {fis.close();} catch (IOException e1) {e1.printStackTrace();}}}}/*** 下载视频文件 path为本地文件路劲** @param path* @param request* @param response*/public void play(String path, HttpServletRequest request, HttpServletResponse response) {RandomAccessFile targetFile = null;OutputStream outputStream = null;try {outputStream = response.getOutputStream();response.reset();//获取请求头中Range的值String rangeString = request.getHeader(HttpHeaders.RANGE);//打开文件File file = new File(path);if (file.exists()) {//使用RandomAccessFile读取文件targetFile = new RandomAccessFile(file, "r");long fileLength = targetFile.length();long requestSize = (int) fileLength;//分段下载视频if (StringUtils.isNotEmpty(rangeString)) {//从Range中提取需要获取数据的开始和结束位置long requestStart = 0, requestEnd = 0;String[] ranges = rangeString.split("=");if (ranges.length > 1) {String[] rangeDatas = ranges[1].split("-");requestStart = Integer.parseInt(rangeDatas[0]);if (rangeDatas.length > 1) {requestEnd = Integer.parseInt(rangeDatas[1]);}}if (requestEnd != 0 && requestEnd > requestStart) {requestSize = requestEnd - requestStart + 1;}//根据协议设置请求头response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes");response.setHeader(HttpHeaders.CONTENT_TYPE, "video/mp4");long length;if (requestEnd > 0) {length = requestEnd - requestStart + 1;response.setHeader(HttpHeaders.CONTENT_LENGTH, "" + length);response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + requestStart + "-" + requestEnd + "/" + fileLength);} else {length = fileLength - requestStart;response.setHeader(HttpHeaders.CONTENT_LENGTH, "" + length);response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + requestStart + "-" + (fileLength - 1) + "/"+ fileLength);}
//                    }boolean scPartialContent = true;//断点传输下载视频返回206//如果是第一次请求,不返回206if (ranges.length > 1) {String[] rangeDatas = ranges[1].split("-");requestStart = Integer.parseInt(rangeDatas[0]);if (rangeDatas.length > 1 && requestStart == 0 && Integer.parseInt(rangeDatas[1]) == 1) {
//                            requestEnd = Integer.parseInt(rangeDatas[1]);scPartialContent = false;log.info("第一次请求rangeString,{}", rangeString);}}if (scPartialContent) {log.info("不是第一次请求rangeString,{}", rangeString);response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);}//设置targetFile,从自定义位置开始读取数据targetFile.seek(requestStart);} else {//如果Range为空则下载整个视频response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=test.mp4");//设置文件长度response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(fileLength));}//从磁盘读取数据流返回byte[] cache = new byte[4096];try {while (requestSize > 0) {int len = targetFile.read(cache);if (requestSize < cache.length) {outputStream.write(cache, 0, (int) requestSize);} else {outputStream.write(cache, 0, len);if (len < cache.length) {break;}}requestSize -= cache.length;}} catch (IOException e) {// tomcat原话。写操作IO异常几乎总是由于客户端主动关闭连接导致,所以直接吃掉异常打日志//比如使用video播放视频时经常会发送Range为0- 的范围只是为了获取视频大小,之后就中断连接了log.info(e.getMessage());}} else {
//                throw new RuntimeException("文件路劲有误");}outputStream.flush();} catch (Exception e) {log.error("文件传输错误", e);
//            throw new RuntimeException("文件传输错误");} finally {if (outputStream != null) {try {outputStream.close();} catch (IOException e) {log.error("流释放错误", e);}}if (targetFile != null) {try {targetFile.close();} catch (IOException e) {log.error("文件流释放错误", e);}}}}}

视频格式问题,参考地址https://zhuanlan.zhihu.com/p/532430872

我们的对比发下,上传的视频帧速率为25帧/秒无法播放,帧速率为30帧/秒可以正常。这和上述链接中讲解的苹果对视频帧数支持和格式说明有关系。

于是我们使用格式工厂(视频处理工具,免费的),进行转换后上传,真的可以正常播放了。到此问题全部解决。

苹果手机 h5网页或公众号视频无法播放问题处理相关推荐

  1. uniapp中h5网页微信公众号授权

    uniapp微信网页授权 uniapp中h5网页微信公众号授权 主要代码 获取code返回的code截取代码 uniapp中h5网页微信公众号授权 微信官方文档–>网页授权 uniapp中h5网 ...

  2. 公众号视频化|公众号如何添加视频内容

    在生活节奏日益加快的当下,短视频这种信息传达更直观.表现形式更多元的内容形式越来越受到用户欢迎.尤其伴随着5G时代的到来,整个社会似乎已经进入一个无视频不欢的"新时代". 那么,内 ...

  3. 骏飞H5幸运刮刮乐源码多级分佣+upupw直接架设+H5微信登陆公众号接入 管理员

    简介: 骏飞H5幸运刮刮乐源码多级分佣+upupw直接架设+H5微信登陆公众号接入 管理员 网盘下载地址: http://kekewl.net/pWg5xjUEhkm0 图片:

  4. 2021最新外卖霸王餐小程序、H5、微信公众号版外系统源码|霸王餐美团/饿了么系统 粉丝裂变玩源码下载

    2021年了,你还在用淘宝客吗?赶紧跟上互联网的大势吧,外卖cps就是cps人群趋势! 个人.个体.企业均可使用 外卖霸王餐小程序.H5.微信公众号版外系统源码|霸王餐美团/饿了么系统 粉丝裂变玩 2 ...

  5. 普通人的机会来了,微信公众号视频的推荐机制,助力自媒体变现

    最近微信公众号的视频推荐分发机制,给我带来了挺多惊喜. 几个月前,偶然把我媳妇做头条号的一个视频发到了公众号,过了大半个月发现居然有5000多的播放量.看到这个数据,我很差异,难道公众号现在开始对视频 ...

  6. 公众号+视频号+个人号的闭环运营将非常重要

    2020年10月9日,抖音直播正式切断和第三方平台的合作,开始打造自己的封闭生态系统. 与此同时,微信团队在这一时间段内,开始不同寻常的快速迭代视频号,并且逐步放开微信生态内的所有权限,包括流量采买( ...

  7. python爬微信公众号视频_python爬虫公众号所有信息,并批量下载公众号视频

    之前写过一篇类似的文章:python爬取公众号,用最简单的方式爬虫 还有同学一直在问,可能中间有一些小细节不明确,这次彻底明确一下细节. 本篇添加一个批量下载公众号内视频的功能,可以实现完全复制一个公 ...

  8. python爬取某信公众号所有信息,并批量下载公众号视频

    本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理 以下文章来源于腾讯云 作者:Python疯子 本篇添加一个批量下载公众号内视频的功 ...

  9. springboot+h5页面+微信公众号获取微信用户信息

    springboot项目,h5页面通过微信公众号获取微信用户信息 最近本人有一个项目需求,微信公众号里点击一个菜单进入一个商城购物系统. 对于在微信公众号还是小白的我来说难度有点大,但是做完后发现也就 ...

最新文章

  1. FreeModbus 移植于STM32 实现Modbus RTU通信
  2. TortoiseSVN找不到系统指定路径
  3. pixysoft.framework.messageflow enterprise edition 开发实录
  4. 对于新生代农民工,你有什么想说的?
  5. kmp算法字符串匹配C语言实现
  6. 摘来的去视频网站的广告方法
  7. kotlin中的异常处理_Kotlin异常处理
  8. linux---編輯器
  9. bat窗口大小设置_如何将U盘设置成我们计算机的开机秘钥,对电脑加密。
  10. C++ 编译运行报错 error: stray ‘\200’ in program 解决方案
  11. win8更改计算机锁屏时间,win8如何设置电脑屏保时间设置方法
  12. OpenCV学习:找出人脸,同时比较两张图片中的人脸相似度
  13. Android流星雨效果---史上最炫,浪漫,值得陪你女朋友一起看~ [捂脸]
  14. linux 查看java进城_linux查看java进程|线程池信息
  15. OCAD应用:单透镜与双胶合透镜结构组合设计
  16. 故障分析 | 从 data_free 异常说起
  17. python stm32 usb bulk_STM32-USB学习笔记(一) USB基础
  18. Asp.Net初学小结 判断数组中是否有重复的数据
  19. Django QuerySet优化
  20. Antv X6中的markup和attr是如何配合使用的

热门文章

  1. java swing中国象棋聊天室对战游戏
  2. git push 报错:fatal: unable to access ‘https://github.com/...‘......
  3. 2022年湖南省自考考试学前教育原理练习题及答案
  4. 管理上的心得分享(三)
  5. 嵌入式工程师是如何炼成的
  6. 基于KEAZ128的bootloader实现(LIN)
  7. 计算机技术在焊接方面的应用,计算机技术在焊接过程控制中的应用
  8. 政府机构机房环境监控系统解决方案!
  9. 唯品会开源定时器框架Saturn
  10. 解决Altium Designer线宽、过孔参数与规则不符