这是我参与「第五届青训营 」伴学笔记创作活动的第 15 天
使用ffmpeg进行视频流的处理和学习
在本次青训营项目中,由于需要有视频上传功能的投稿接口,因此在之前我使用的是通过先将上传的视频暂存在本地的Ubuntu服务器的临时文件储存目录中,之后再通过go语言执行cmd命令调用ffmpeg命令行工具,以此将视频进行第一帧进行截图操作,并将获得的图片暂存再临时目录中,之后再将分别将视频和图片文件上传到minio中进行存储,这样的操作效率较低,浪费了很多不必要的时间与资源。并且之后通过学习别人的方式决定将前端发送过来的视频流直接转送到云存储 MinIO 中,通过获得url链接对该存储对象直接操作截取视频并将输出视频封面同样转存到云存储 MinIO 中。
不管是视频还是图片或者其他形式的文件都可以通过UploadFile函数进行上传,传入参数为bucketName(文件归属的桶),objectName(文件名称),reader(数据流),contentType(文件类型例如MP4 jpg),objectSize(文件大小),其中主要调用了
"github.com/minio/minio-go/v7"包中的PutObject函数
// UploadFile 上传文件(提供reader)至 minio
func UploadFile(bucketName string, objectName string, reader io.Reader, contentType string, objectSize int64) error {
ctx := context.Background()
n, err := minioClient.PutObject(ctx, bucketName, objectName, reader, objectSize, minio.PutObjectOptions{
ContentType: contentType,
})
if err != nil {
log.Printf("upload %s of size %d failed, %s", bucketName, objectSize, err)
return err
}
log.Printf("upload %s of bytes %d successfully", objectName, n.Size)
return nil
}
通过Getimagestream这个函数获得截图,输入参数为https://www.w3schools.com/html/movie.mp4这样的视频url的string字符串,输出为截图的视频流,数据大小,和是否出错
func Getimagestream(inputFile string) (io.Reader, int64, error) {
// 设置 FFmpeg 参数及运行
buf := bytes.NewBuffer(nil)
//s
err := ffmpeg_go.Input(inputFile).
Filter("select", ffmpeg_go.Args{fmt.Sprintf("gte(n,%d)", 5)}).
Output("pipe:", ffmpeg_go.KwArgs{"vframes": 1, "format": "image2", "vcodec": "mjpeg"}).
WithOutput(buf, os.Stdout).
Run()
// 结果显示
if err != nil {
log.Fatalln("截取图片失败", err)
return buf, 0, err
}
log.Printf("截取图片成功")
return buf, int64(buf.Len()), nil
}