基于 SCF 利用 FFmpeg 对视频旋转保存

基于 SCF 利用 FFmpeg 对视频旋转保存

之前在上家公司有个项目需要上传小视频然后在小程序进行轮播式显示,但是从抖音找的测试视频发现可能是上传者的问题,下载下来视频是竖向的,现在离职后比较有时间所以做了下研究。

流程图

这里我使用 SCF 通过 FFmpeg 来达到我们的目的。流程是我们监听对象存储的上传操作,然后对上传的视频进行一个判断转换,不太了解如何去判断视频的一个方向这里只是做了旋转 90° 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<?php

require './cos-php-sdk-v5/vendor/autoload.php';

use Qcloud\Cos\Client;

function main_handler($event, $context) {
$event = json_decode(json_encode($event), true);

$context = (array) $context;

$request_id = $context['request_id'];

// 判断事件是否为 COS 触发
if(!isset($event['Records']) || !isset($event['Records'][0]['cos'])) {
return 0;
}

$event = $event['Records'][0]['cos'];

// 获取地域。注意:这里获取到是简写的,例如 gz
$region = $event['cosBucket']['region'];

// 实例化 COS SDK 客户端
$cos = new Client([
'region' => $region,
'schema' => 'https',
'credentials' => [
'secretId' => getenv('cos_secret_id'),
'secretKey' => getenv('cos_secret_key'),
],
]);

$bucket = $event['cosBucket']['name'] . '-' . $event['cosBucket']['appid'];

// 文件 KEY。例如:/1252156936/ffmpeg/upload/1.mp4
$key = $event['cosObject']['key'];

// 文件名。例如:1.mp4
$name = end(explode('/', $key));

// 文件路径。例如:ffmpeg/upload/1.mp4
$path = substr($key, strlen($bucket) + 2);

// 下载临时路径
$tmp_path = '/tmp/' . $request_id . '.mp4';

// 下载文件
$cos->getObject([
'Bucket' => $bucket,
'Key' => $path,
'SaveAs' => $tmp_path
]);

// 通过 ffprobe 获取文件信息
exec('/var/user/ffmpeg/ffprobe -v quiet -print_format json -show_format -show_streams ' . $tmp_path, $output);

// 获取到的信息有点乱所以这边做了下处理。
$ffprobe = json_decode(preg_replace('/s(?=s)/', '', implode('', $output)), true);

$info = $ffprobe['streams'][0];

// 如果视频宽度比高度大就不需要处理
if($info['width'] >= $info['height']) {
return 0;
}

// 拷贝临时路径
$copy_path = '/tmp/' . $request_id . '_copy.mp4';

// 对视频文件进行旋转
system('/var/user/ffmpeg/ffmpeg -i ' . $tmp_path . ' -metadata:s:v rotate="90" -codec copy ' . $copy_path);

if(file_exists($copy_path)) {
$cos->Upload($bucket, getenv('storage_prefix') . $name, fopen($copy_path, 'rb'));

unlink($copy_path);
}

unlink($tmp_path);

return 1;
}

?>

配置

环境变量:

1
2
3
cos_secret_id=  # COS secret id
cos_secret_key= # COS secret key
storage_prefix= # 存储前缀

触发方式:

这里事件类型要为 Put 方法创建,然后后缀过滤写 .mp4

测试

测试视频:
1.mp4
2.mp4
3.mp4
4.mp4
5.mp4
6.mp4

函数内存是 256 M,上面几个视频基本都是 1M 大小,这边进行了一百多次上传。统计了最后 100 次运行,平均耗时 290ms 。

参考

ffmpeg安装
ffmpeg/ffprobe查看音频视频文件信息并输出为json格式


源码下载

往上