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

news/2024/11/28 10:39:14/

最近遇到奇葩问题,苹果手机公众号和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帧/秒可以正常。这和上述链接中讲解的苹果对视频帧数支持和格式说明有关系。

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


http://www.ppmy.cn/news/516591.html

相关文章

湖大CG满分教程:作业训练一编程题4. 欧洲冠军联赛

【问题描述】 欧洲冠军联赛常被誉为全世界最具影响力的俱乐部级赛事。在比赛的小组赛阶段&#xff0c;欧洲的各个足球俱乐部被分为八个小组&#xff0c;每个小组中四支球队。每个小组中的球队按照如下规则排序&#xff1a; 球队会根据比赛结果获得积分。一场比赛的双方被称为主…

关于oss视频、语音不能播放问题

最近公司让做微信端上传视频或者语音&#xff0c;然后后台审核功能&#xff0c;微信可以正常拿到数据&#xff0c;但是在web展示的时候&#xff0c;视频和语音都不可以正常播放。后来找原因&#xff0c;是因为https的content-type的问题&#xff0c;因为上传的时候没有指定cont…

iphone php格式视频播放,iPhone能播放什么格式的视频 支持视频格式

【巴士数码】一些新手用户可能还不清楚iPhone能播放什么格式的视频&#xff0c;下面我们就来详细介绍一下iPhone6播放视频格式。iPhone6屏幕变大了&#xff0c;观看视频时自然拥有更好的视觉效果&#xff0c;不过在此之前&#xff0c;我们还得弄清楚iPhone6支持播放什么格式的视…

java视频上传,播放预览,解决苹果手机视频无法预览的问题

需求&#xff1a;上传视频后&#xff0c;点击链接可以在PC和手机端播放预览&#xff0c;包括苹果手机 1.相关工具类 1.1文件上传工具类 package resources.util;import common.util.FileOperateUtil; import common.util.HttpClientUtil; import net.sf.json.JSONObject; im…

如何从苹果手机中导出视频且保证画面不失真

最近买了iPhone 12&#xff0c;因为工作需要需要导出视频&#xff0c;但是手机连上电脑后&#xff0c;如何导出视频且保证清晰度是个问题&#xff0c;尝试了一下&#xff0c;特此记录&#xff0c;供大家参考&#xff01; 1、手机设置 设置——相册——“传输到MAC或PC”&…

使用wxParse解析富文本的总结以及解决苹果手机上视频无法播放的方法

先上官方文档&#xff1a;https://github.com/icindy/wxParse。先讲一下我的理解&#xff0c;最后说明下自己使用wxParse的业务场景以及遇到的问题。 1.先上个目录结构。 然后总结下wxParse下我处理过得文件。html2json.js中注释掉console.dir()---显示对象的属性跟方法&#…

如何禁止视频在手机移动端页面中全屏播放

最近公司的项目中出了需要在局部播放视频的需求&#xff0c;我们都知道HTML5中有一个专门的标签video用来嵌入视频。不过&#xff0c;这个video标签有很多的属性可能很多同学并不是很熟悉&#xff0c;下面我们来认识一下&#xff1a; 在网页里嵌入HTML5视频播放器的方法非常简单…

iPhone下mp4视频无法播放和部分手机只有声音没有画面

概述 mp4视频在部分手机上加载失败、无法播放或有声音没画面的原因是&#xff1a;视频编码或声道数有问题&#xff0c;解决方案&#xff1a;视频转码。 遇到的问题 mp4视频在 iPhone XR (IOS 14.1) 上无法播放&#xff0c;一直显示加载失败&#xff0c;但是在安卓手机上却可以…