关于视频播放、视频切片、跨域访问视频

前言

最近在着手部署上线做的一个视频网站,当我们部署到云服务器上后并开始测试视频观看并发量,发现了一个很严重的问题:带宽不足。9 或 10 个人同时观看视频的时候,就会出现有些用户加载不了视频的问题。

我们的云服务器是 1块钱的腾讯云,本身带宽就很低了,所以肯定没有足够大的带宽来支撑这么大的流量传输。这对于一个视频网站来说,带宽这个问题是非常致命的。在不能改变带宽的条件下,于是我们去找了一些方法来提高性能。

分析不足

我们的视频网站使用的内置 Flash 播放器来播放视频,用户观看视频的时候是直接完全加载整个视频的(不管你看了多久),从一开始播放就开始加载,并且并不会因为用户暂停而暂停加载, 它是一直持续加载直到加载完全的。对于绝大多数用户来说,他们不一定会把视频看完,如果是加载一个小视频,那还没有什么大问题,但如果是加载一个大视频的话,这就会浪费的大量的流量,并且加载过程会持续占用带宽,使得用户量多的时候,视频加载就会出现问题。

修改第一步

了解到这个问题之后,我们去看了别人的视频网站是如何撑起高用户量的,在视频播放的时候,我们发现它们并不是一开始就完全加载视频的,而是一段段的加载,去搜索之后发现这是一种切片的技术,用于控制流量传输。具体的切片的原理可参看 http://www.cnblogs.com/flash3d/archive/2013/11/02/3403109.html。

了解了切片技术之后,我们于是就开始在我们项目中应用切片的技术,我们使用的是 ffmpeg 来对视频进行切片。方法就是在程序中调用 ffmpeg 程序,然后调用切片命令对我们的视频进行切片,生成 m3u8 文件和 ts 文件,然后使用 flash 播放器播放,能够看到的确能够一段段的加载视频。

修改到这一步,这似乎解决了我们的问题,但是新的问题又出现了,我们发现当我们对大视频进行切片的时候,服务器的内存会占用很大,至于为什么会占用那个大,我们猜想可能是因为对视频切片时,ffmpeg 把整个视频加载到内存,所以导致内存占用高。当同时对多个视频进行切片的时候,服务器就炸掉了。于是我们又寻求新的方法去解决。

修改第二步

因为没想到好的方法去解决本地切片内存占用问题,于是我们使用了新的途径去存储播放视频,就是使用云端存储来存储视频,我们选用的是七牛云服务器来存储。它也提供了不同语音的 SDK 供开发者参考。

使用七牛云,我在我的 Java Web 项目里面导进必须的 4 个包,以及编写了上传视频并进行切片预处理的工具类。刚开始使用的时候也遇到许多问题。

问题1:上传不同格式的视频,有些播放不了

一开始,我们对任何格式的视频都调用同一个切片命令,以为会生成同一种格式的视频文件。但是当我们上传的 MP4 格式的视频,切片上传后,直接在浏览器输入外链(文件的访问链接),此时能够正常播放;但是上传 avi 或者 flv 格式的视频,上传切片后,直接输入外链会变成下载文件。

当时一直想不通这个问题的原因,因为明明都是调用了同一个命令切片,按理来说应该格式是一样的,但是却出现不同的行为。后来通过七牛云的问答平台寻求解决方案,才发现如果在上传的时候,没有使用 saveas 参数对结果另存为 xxx.m3u8 格式,他还是任然会以原有的格式去保存。所以基于浏览器对不同视频格式的支持,对 mp4、avi、flv等格式的视频则出现不同的效果

问题2: 使用外链播放出现跨域拒绝的问题

在我们解决完视频上传的问题之后,在播放器通过外链来播放视频的时候,发现出现跨域被拒绝的问题 (ERROR:HLSError(code/url/msg)=1tp:Cannot load M3U8: crossdomain access denied:Error #2048),google 了问题,发现原来Flash 播放器在加载跨域视频时,会先去加载云端的 corssdomain.xml 文件,然后判断是否被允许加载。

解决方法:需要在七牛云端上传 crossdomian.xml 文件

Java 七牛云上传视频的工具类

基于七牛云的 API,写了一个上传视频并切片的接口,可供参考;如有错 ,可一起讨论

该接口的配置信息采用配置文件 video.properties 来加载,具体的配置文件配置内容为:

access_key=your access key

secert_key=your secert key

bucketname=你的存储空间

pipeline=你的多媒体处理队列名

fops=avthumb/m3u8/noDomain/1/vb/500k/t/120(这是切片命令)若是要做其他处理,请参照七牛云 SDK

domain=你的七牛云映射域名

public class QiNiuUtil {

private static String DEFAULT_PROPERTIES = "video.properties";

private static Properties properties = new Properties();

static {

String path = QiNiuUtil.class.getResource("/").toString();

path = path.substring(6, path.length() - 8) + DEFAULT_PROPERTIES;

System.out.println(path);

try {

FileInputStream fileInputStream = new FileInputStream(path);

properties.load(fileInputStream);

System.out.println(properties.toString());

} catch (IOException e) {

System.out.println("配置文件不存在,加载配置文件失败");

}

}

public static String domian = properties.getProperty("domain");

private static String ACCESS_KEY = properties.getProperty("access_key");

private static String SECRET_KEY = properties.getProperty("secert_key");

// 要上传的空间

private static String bucketname = properties.getProperty("bucketname");

// 设置切片操作参数

private static String fops =properties.getProperty("fops");

// 设置转码的队列

private static String pipeline = properties.getProperty("pipeline");

//密钥配置

private static Auth auth = Auth.create(ACCESS_KEY, SECRET_KEY);

//创建上传对象

private static UploadManager uploadManager = new UploadManager();

//上传策略中设置persistentOps字段和persistentPipeline字段

public static String getUpToken(String pfops){

return auth.uploadToken(bucketname,null,3600,new StringMap()

.putNotEmpty("persistentOps", pfops)

.putNotEmpty("persistentPipeline", pipeline), true);

}

public static boolean upload(byte[] data, String key) throws IOException{

Response res = null;

try {

// 调用put方法上传

// 指定文件以 m3u8 格式另存

String urlbase64 = UrlSafeBase64.encodeToString(bucketname + ":" + key + ".m3u8");

res = uploadManager.put(data, key, getUpToken(fops + "|saveas/"+ urlbase64));

//打印返回的信息

System.out.println(res.bodyString());

} catch (QiniuException e) {

Response r = e.response;

// 请求失败时打印的异常的信息

System.out.println(r.toString());

try {

//响应的文本信息

System.out.println(r.bodyString());

} catch (QiniuException e1) {

//ignore

}

}

return res.isOK();

}

}

java 视频切片_关于视频播放、视频切片、跨域访问视频相关推荐

  1. java设置access-allow_Java中设置多个Access-Control-Allow-Origin跨域访问

    1.如果服务端是Java开发的,添加如下设置允许跨域即可,但是这样做是允许所有域名都可以访问,不够安全. response.setHeader("Access-Control-Allow-O ...

  2. ashx 跨域_使用ashx解决ajax跨域访问的问题

    由于跨域访问是被IE的安全访问拒绝掉的 需要使用web代理 新建一个proxy.ashx文件 在proxy.ashx里建一个webservice 代码如下: [WebService(Namespace ...

  3. ashx 跨域_使用ashx解决ajax跨域访问的问题 | 学步园

    由于跨域访问是被IE的安全访问拒绝掉的 需要使用web代理 新建一个proxy.ashx文件 在proxy.ashx里建一个webservice 代码如下: [WebService(Namespace ...

  4. ajax 请求_前端后分离Ajax跨域请求保证Session一致

    JAVA码牛牛,程序员学习指南 前后端分离的项目,使用Ajax请求一般都出现跨域的问题. 跨域的时候所创建的session是不会被浏览器保存下来的.所以每次进行跨域请求时,服务器都认为不是同一个浏览器 ...

  5. authorization 传 就跨域_跨域访问接口上传图片出现options请求问题解决方法

    1.首先因为服务器端会先发送一个option请求到后台  在后台返回一个post给页面 页面在处理post请求给接口 2.先写一个过滤器, 我们自己定义一个过滤器 package com.adtime ...

  6. yii2 跨域请求配置_如何在SpringBoot应用中实现跨域访问资源和消息通信?

    允许跨域访问 CORS ( Cross Origin Resource Sharing,跨域资源共享)机制允许Web应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行.浏览器支持在API容器中 ...

  7. java 使用oos 进行数据上传和跨域

    java 使用oos 进行数据上传和跨域 导入依赖 <dependency><groupId>com.aliyun.oss</groupId><artifac ...

  8. cas跨域单点登录原理_基于CAS的SSO单点登录-实现ajax跨域访问的自动登录

    先补课,以下网址可以把CAS环境搭起来. [问题背景]两个系统的整合就不说了,简单来说就是网页放在NginX上,但是ajax调用tomcat的API获取数据,其中tomcat段用CAS做身份认证.具体 ...

  9. java跨域解析json数据_java后台设计简单的json数据接口,设置可跨域访问,前端ajax获取json数据...

    在开发的过程中,有时候我们需要设计一个数据接口.有时候呢,数据接口和Web服务器又不在一起,所以就有跨域访问的问题. 第一步:简单的设计一个数据接口. 数据接口,听起来高大上,其实呢就是一个简单的Se ...

最新文章

  1. .net mvc actionresult 返回字符串_字符串游戏之无效的身份证
  2. Google下重手了!安卓App广告弹窗被打击
  3. JSTL EL对Map集合的支持
  4. IIS识别Json文件
  5. sum of two integers
  6. 【NOIP 模拟赛】 道路
  7. LinuxC高级编程——进程
  8. 2019.1.31及以前
  9. 吴恩达机器学习【第四天】多元线性规划模型
  10. itext汇总 生成pdf
  11. PAT 1074. 宇宙无敌加法器(20)-PAT乙级真题
  12. zabbix使用ICMP ping监控网络状态
  13. linux交叉编译环境变量设置,arm-linux-gcc安装 和 环境变量设置
  14. Matlab逆向归纳法,逆向归纳法
  15. 如何在ChemDraw中输入℃温度符号
  16. oracle能用hql吗,使用HQL查询日期,Oracle报“Invalid number”
  17. rt3070网卡 linux驱动,移植rt3070芯片网卡驱动到dm365全过程---yingru
  18. 转载 Python 学习-Matplotlib库
  19. 工具用得好,下班走得早,这个OCR识别是真的好用
  20. 坚持就是胜利,坚持就是升华

热门文章

  1. linux 自定义外壳,管道在自定义的linux外壳
  2. 超硬核,整理的这10个自动化测试框架,使用后简直如有神助
  3. suse linux 备份,suse linux利用scp实现自动远程备份
  4. java二次开发浏览器内核_常见的五大浏览器的内核
  5. js最简单的几个特效_高阶函数不会用?教你JS中最实用的几个高阶函数用法
  6. ini文件怎么注释_wamp怎么升级php版本
  7. windows下重启mysql数据库_windows下重启mysql的方法
  8. mfc cedit 默认显示内容_VS2013/MFC编程学习(一)
  9. y电容如何选型_陶瓷气体放电管,如何选型?
  10. python函数进阶小结_Python-进阶-functools模块小结