oss 视频 转码_关于使用 ali-oss 进行视频分片上传的一些思考

近期对视频上传进行了相关优化,由原本的上传到后端服务器改为前端直传 all-oss。

出现的问题

阿里云提供了 ali-oss sdk,前端可以很方便的进行直传工作。

但实际使用中也出现了一些问题

取消分片上传

ali-oss 文档中仅提供了 abortMultipartUpload 来进行取消分片上传。

该方法有几个问题前端获取到的 access_token 有效期有一个小时,后端不希望暴露给前端 bucket 的删除权限

abortMultipartUpload 方法调用后会删除已有的上传碎片,后续无法做断点续传功能。

在源码中看到在 proto 挂了一个 cancel 方法,可以直接调用https://github.com/ali-sdk/ali-oss/blob/c87f6dab60de065e94e522fdc3bc0b27b94135e4/lib/common/thunkpool.js#L87​github.com

另外在 readme 里找到了这样的一段话

//the other event to cancel, for example: click event//to cancel upload must use the same client instancestore.cancel();

OSS 实际上提示提供了一个 cancel 方法,但并没有很好的在文档中说明

关于此问题讨论在此:https://github.com/ali-sdk/ali-oss/issues/384​github.com

Cannot read property 'crypto' of undefined

ali-oss sdk 的包大约在 500kb 左右,直接引用源码,有使用 generator,还需要配置 transform plugin 。

尝试直接引用 dist 目录下的 aliyun-oss-sdk.js ,发现会有报错

Cannot read property 'crypto' of undefined

查遍 ali-oss 也没有找到问题。

最后很怪异的在 aws-sdk-js 的 issues 中查找到了类似问题https://github.com/aws/aws-sdk-js/issues/1566​github.com

改为

var _global = this || window || {}

可以解决问题。

应该是 crypto-browserify@ 1.0.9 出了问题。

阿里云工程师后续有修复计划,关于此问题的讨论在此:https://github.com/ali-sdk/ali-oss/issues/386​github.com

此问题阿里云工程师已修复https://github.com/ali-sdk/ali-oss/pull/390​github.com

包体积优化

在无法引用 aliyun-oss-sdk.js 之后,考虑到其他能够优化的方案。

Dynamic import

关于 Dynamic import 可以在这里了解:https://developers.google.com/web/updates/2017/11/dynamic-import​developers.google.comdynamically importing ES modules​2ality.com

使用 Dynamic import 做动态加载,只有在上传视频操作时才加载 ali-oss 包。

看起来是个不错的选择,很容易就写出了这样的代码

class xxx extends xxx {

getClient = () => {

const {

uploadtoken: {

access_id: accessKeyId,

access_key: accessKeySecret,

access_token: stsToken,

},

} = this.video

return import('ali-oss').then(OSS => {

this.client = new OSS.Wrapper({

region: 'oss-cn-hangzhou',

bucket: BUCKET,

secure: true,

accessKeyId,

accessKeySecret,

stsToken,

})

})

}

uploadVideo = () => {

return this.getClient().then(() => {

this.client.multipartUpload(objectKey, this.value, {

progress: this.handleProgress,

mime: this.value.type,

callback,

partSize,

})

}

}

}

实际在项目中使用后,却报错无法使用

Unexpected token: name (Mime) [./node_modules/ali-oss/shims/mime.js:8,0]

[main.3.946eb92154661ba849d7.js:10626,8]

原因是直接引用源码,需要添加 generator transform。虽然可以解决问题,但并不能满足我们的优化策略。需要考虑其他方案。

关于此问题的讨论在此:https://github.com/ali-sdk/ali-oss/issues/362​github.com

get script

ali-oss 提供了一个可以使用的 CDN 地址,在无法 import dist 的情况下,get script 也是一个比较好的方案。

把 Dynamic import 的代码改为 get script 即可

import memoize from 'lodash/memoize'

function getScript(source) {

return new Promise(resolve => {

let script = document.createElement('script')

const prior = document.getElementsByTagName('script')[0]

script.async = 1

script.onload = script.onreadystatechange = function(_, isAbort) {

if (

isAbort ||

!script.readyState ||

/loaded|complete/.test(script.readyState)

) {

script.onload = script.onreadystatechange = null

script = undefined

if (!isAbort) {

resolve()

}

}

}

script.src = source

prior.parentNode.insertBefore(script, prior)

})

}

const importScript = memoize(getScript)

class xxx extends xxx {

getClient = () => {

const {

uploadtoken: {

access_id: accessKeyId,

access_key: accessKeySecret,

access_token: stsToken,

},

} = this.video

return importScript('http://gosspublic.alicdn.com/aliyun-oss-sdk-4.13.2.min.js').then(OSS => {

this.client = new window.OSS.Wrapper({

region: 'oss-cn-hangzhou',

bucket: BUCKET,

secure: true,

accessKeyId,

accessKeySecret,

stsToken,

})

})

}

uploadVideo = () => {

return this.getClient().then(() => {

this.client.multipartUpload(objectKey, this.value, {

progress: this.handleProgress,

mime: this.value.type,

callback,

partSize,

})

}

}

}

callback

文档中解释 CallBack参数是由一段经过base64编码的Json字串。

但实际传入的时候直接传入对象即可,ali-oss 的 encodeCallback 进行了 base64编码 等操作。

https://github.com/ali-sdk/ali-oss/blob/master/lib/common/callback.js​github.com

分片大小

OSS 最大分片数量不能超过1000个,每个分片大小不能小于 100kb (最后一个分片除外)。

目前的方案是分成 50个分片,如果分成的分片小于 128kb,则分片大小设置为 128kb

分片太小会导致上传失败率增高,如果数据异常则会尝试增加分片的大小。

对于低于 10M 的视频,后续可以考虑不采用分片上传的方法。

断点续传

ali-oss sdk 提供断点续传的方法,关于断点续传,主要有两种思路checkpoint保存到浏览器的localstorage,下次再调用的时候传入checkpoint参数

浏览器不做操作,checkpoint保存在后端,上传之前先去先去服务端请求查看是否有保存的 checkpoint

相比较来说,第一种方法实现起来更简单,也比较方便,不需要后端做额外的操作。

其他总结

直传 ali-oss 让视频上传速度提高了一倍,但转码速度依旧很慢,后续需要针对转码进行额外的优化。


版权声明:本文为weixin_42298378原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。