首页 > 其他分享 >golang 使用ffmpeg工具实现音视频转码

golang 使用ffmpeg工具实现音视频转码

时间:2023-07-08 18:32:21浏览次数:35  
标签:return ffmpeg 转码 cmd 音视频 log func srcPath string

1 ffmpeg工具是什么

FFmpeg即是一款音视频编解码工具,同时也是一组音视频编码开发套件,作为编码开发套件,它为开发者提供了丰富的音视频处理的调用接口。

FFmpeg提供了多种媒体格式的封装和解封装,包括多种音视频编码、多种协议的流媒体、多种多彩格式转换、多种采样率转换、多种码率转换等;FFmpeg框架提供了多种丰富的插件模块,包含封装与解封装的插件、编码与解码的插件等。

2 ffmpeg工具类

项目pakage:

golang 使用ffmpeg工具实现音视频转码_封装

2.1 获取编码格式NeedTranscode

golang 使用ffmpeg工具实现音视频转码_ide_02

2.2 获取时长getDuration

2.3 获取码率getCodeRate

golang 使用ffmpeg工具实现音视频转码_封装_03

2.4 获取分辨率getResRate

golang 使用ffmpeg工具实现音视频转码_ide_04

2.5 转码transcode

指定转码格式加参数 -c:a  -c:v  type  a是Audio(音频) v是Video(视频)

ps:

ffmpeg -i input_file.ext -c:a aac output_file.aac
 ffmpeg -i input_file.ext -c:v aac output_file.mp4

golang 使用ffmpeg工具实现音视频转码_封装_05

2.6 源文件ffmpeg_util.go

package ffmpeg_util

import (
	"fmt"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"support/logger"
)

type IFfmpegTranscode interface {
	NeedTranscode(srcPath string) (bool, error)
	Transcode(srcPath, dstPath string) error
	GetDuration(srcPath string) (int, error)
	GetCodeRate(srcPath string) (int, error)
	GetResRate(srcPath string) (string, error)
}

// 默认转码格式为文件名后缀
func transcode(log logger.ILog, srcPath, dstPath string) error {
	cmd := exec.Command(getTranscodeTool(), "-i", srcPath, dstPath)
	res, err := cmd.CombinedOutput()
	log.Debug("ffmpeg exec srcPath: %s, result: %s", srcPath, res)
	return err
}

// 获取音视频时长
func getDuration(log logger.ILog, srcPath string) (int, error) {
	cmd := exec.Command(getBashTool(), "-c")
	arg := fmt.Sprintf(`%s -i %s 2>&1 | grep -m 1 'Duration:' | cut -d ' ' -f 4 | sed s/,// |  awk -F ":" '{ print (($1*3600) + ($2*60) + $3) * 1000 }'`,
		getTranscodeTool(), srcPath)
	cmd.Args = append(cmd.Args, arg)
	res, err := cmd.CombinedOutput()
	log.Debug("ffmpeg exec srcPath: %s, cmd:%s, result: %s", srcPath, arg, res)
	if err != nil {
		return 0, err
	}
	if len(string(res)) == 0 {
		return 0, nil
	}
	// Chrome只支持标准的H.264编码
	durStr := strings.Trim(string(res), "\n")
	return strconv.Atoi(durStr)
}

// 获取码率
func getCodeRate(log logger.ILog, srcPath string) (int, error) {
	cmd := exec.Command(getBashTool(), "-c")
	arg := fmt.Sprintf(`%s -i %s 2>&1 | grep 'Audio:' | grep -m 1 'Hz'| awk -F "," '{print $2}'| awk -F " " '{print $1}'`,
		getTranscodeTool(), srcPath)
	cmd.Args = append(cmd.Args, arg)
	res, err := cmd.CombinedOutput()
	log.Debug("ffmpeg exec srcPath: %s, cmd:%s, result: %s", srcPath, arg, res)
	if err != nil {
		return 0, err
	}
	// Chrome只支持标准的H.264编码
	resStr := strings.Trim(string(res), "\n")
	if len(resStr) == 0 {
		return 0, nil
	}
	return strconv.Atoi(resStr)
}

// 获取分辨率
func getResRate(log logger.ILog, srcPath string) (string, error) {

	cmd := exec.Command(getBashTool(), "-c")
	arg := fmt.Sprintf(`%s -i %s 2>&1 | grep 'Video:' | grep -m 1 'fps' `,
		getTranscodeTool(), srcPath)
	cmd.Args = append(cmd.Args, arg)
	res, err := cmd.CombinedOutput()
	if err != nil {
		return "", err
	}

	log.Debug("ffmpeg exec srcPath: %s, cmd:%s, result: %s", srcPath, arg, res)

	resStr := extractResolution(string(res))
	return resStr, nil
}
func extractResolution(input string) string {
	re := regexp.MustCompile(`\b(\d{3,4}x\d{3,4})\b`)
	matches := re.FindStringSubmatch(input)
	if len(matches) < 2 {
		return ""
	}
	return matches[1]
}

func needTranscode(log logger.ILog, srcPath, streamType, coderType string) (bool, error) {
	cmd := exec.Command(getBashTool(), "-c")
	arg := fmt.Sprintf(`%s -i %s 2>&1 | grep 'Stream' | grep -m 1 '%s:' | sed s/,// | awk -F " " '{ print $4 }'`,
		getTranscodeTool(), srcPath, streamType)
	cmd.Args = append(cmd.Args, arg)
	res, err := cmd.CombinedOutput()

	log.Debug("needTranscode exec srcPath: %s, cmd:%s, result: %s", srcPath, arg, res)

	if err != nil {
		return false, err
	}
	// Chrome支持标准的H.264编码以及MP3编码
	coder := strings.Trim(string(res), "\n")
	if coder == coderType {
		return false, nil
	}
	return true, nil
}

3 系统差异

3.1 program_linux.go

package ffmpeg_util

func getTranscodeTool() string {
	return "ffmpeg"
}

func getBashTool() string {
	return "bash"
}

3.2 program_windows.go

package ffmpeg_util

func getTranscodeTool() string {
	return "./resource/ffmpeg.exe"
}

func getBashTool() string {
	return "D:\\install\\Git\\bin\\bash.exe"
}

4 客户端

4.1 audio_client.go

package ffmpeg_util

import (
	"support/logger"
)

const coderMp3 = "mp3"
const Audio = "Audio"

type audioTranscode struct {
	log logger.ILog
}

func NewAudioTranscode(log logger.ILog) *audioTranscode {
	return &audioTranscode{
		log: log,
	}
}

func (at *audioTranscode) NeedTranscode(srcPath string) (bool, error) {
	return needTranscode(at.log, srcPath, Audio, coderMp3)
}

func (at *audioTranscode) Transcode(srcPath, dstPath string) error {
	return transcode(at.log, srcPath, dstPath)
}
func (at *audioTranscode) GetDuration(srcPath string) (int, error) {
	return getDuration(at.log, srcPath)
}

func (at *audioTranscode) GetCodeRate(srcPath string) (int, error) {
	return getCodeRate(at.log, srcPath)
}
func (at *audioTranscode) GetResRate(srcPath string) (string, error) {
	return "", nil
}

4.2 video_client.go

4.2.1 获取视频封面

golang 使用ffmpeg工具实现音视频转码_封装_06

package ffmpeg_util

import (
	"os/exec"
	"support/logger"
)

const coderH264 = "h264"
const Video = "Video"

type videoTranscode struct {
	log           logger.ILog
	transcodeTool string
	bashTool      string
}

func NewVideoTranscode(log logger.ILog) *videoTranscode {
	return &videoTranscode{
		log:           log,
		transcodeTool: getTranscodeTool(),
		bashTool:      getBashTool(),
	}
}

func (vt *videoTranscode) NeedTranscode(srcPath string) (bool, error) {
	return needTranscode(vt.log, srcPath, Video, coderH264)
}

func (vt *videoTranscode) Transcode(srcPath, dstPath string) error {
	return transcode(vt.log, srcPath, dstPath)
}
func (vt *videoTranscode) GetDuration(srcPath string) (int, error) {
	return getDuration(vt.log, srcPath)
}
func (vt *videoTranscode) GetCodeRate(srcPath string) (int, error) {
	return getCodeRate(vt.log, srcPath)
}
func (vt *videoTranscode) GetResRate(srcPath string) (string, error) {
	return getResRate(vt.log, srcPath)
}

// CaptureCover 视频截取第一帧当封面
func CaptureCover(log logger.ILog, srcPath string, coverPath string) error {
	cmd := exec.Command(getTranscodeTool(), "-i", srcPath)
	cmd.Args = append(cmd.Args, "-y", "-f", "image2")
	cmd.Args = append(cmd.Args, "-frames", "1", coverPath)
	res, err := cmd.CombinedOutput()

	log.Debug("ffmpeg exec srcPath: %s, result: %s", srcPath, res)

	return err
}

5.调用示例

golang 使用ffmpeg工具实现音视频转码_bash_07

var ft ffmpeg_util.IFfmpegTranscode

	// 前面做过fileType校验
	switch record.FileType {
	case audioFileType:
		ft = ffmpeg_util.NewAudioTranscode(log)
	case videoFileType:
		ft = ffmpeg_util.NewVideoTranscode(log)
	}

	// 本地转码
	dstPath := path.Join(videoDir, util.GenObjectId()+filepath.Ext(localPath))

	if err = ft.Transcode(localPath, dstPath); err != nil {
		log.Error("fileId:%s trans failed as:%s", record.Id, err)
		return
	}

标签:return,ffmpeg,转码,cmd,音视频,log,func,srcPath,string
From: https://blog.51cto.com/u_12040959/6662786

相关文章

  • ffmpeg指定屏幕区域录屏
    ffmpeg-hide_banner-loglevelerror-fgdigrab-show_region1-framerate6-video_size1914x930-offset_x1921-offset_y105-idesktop-pix_fmtyuv420pout6.mp4 -loglevelerror:只显示错误日志-video_size1914x930-offset_x1921-offset_y105:指定录屏......
  • 机械转码,本来以为只能去比亚迪,没想到十二月份华为、百度、美团等都给我开了...
    作者:阿秀校招八股文学习网站:https://interviewguide.cn你好,我是阿秀。今天分享一位非科班师弟的两年学习经历,他是在上个月的时候跟我私聊说自己上岸华为了,华为给他开的是15级,然后马上就找比亚迪毁约了。。。迪子VS华子,肯定还是华子更香一些的。。。2022.12.19号的事情了秀......
  • aconvert 一个支持多 音视频、多文档格式、压缩包格式转换在线网站
    一个支持多音视频、多文档格式、压缩包格式转换在线网站地址web截图......
  • ffmpeg编码中的一些问题
    1.在查看设备支持的dshow设备时出现:[dshow@00000286dc5e7e40]Couldnotenumeratevideodevices(ornonefound).解决:下载screencapturerecorder并安装(github上有),然后就可以正常使用。2.avformat_open_input打开输入设备时报错返回码为-5?源码如下:extern"C"{#in......
  • EasyCVR平台如何在不修改分辨率的情况下进行H.265自动转码H.264?
    EasyCVR视频融合平台基于云边端一体化架构,可支持多协议、多类型设备接入,在视频能力上,平台可实现视频直播、录像、回放、检索、云存储、告警上报、语音对讲、电子地图、集群、H.265转码、智能分析以及平台级联等。我们在此前的文章中介绍过关于EasyCVR平台H.265自动转码的功能,今......
  • FFmpeg 已支持动画 JPEG-XL
    导读除了Apple宣布在其Safari浏览器中支持JPEG-XL图像格式之外,FFmpeg也宣布现已支持解码动画JPEG-XL文件。去年以来,FFmpeg已经能够使用libjxl库解码静态JPEG-XL图像,随着本周在FFmpeg6.1发布之前合并的提交,现在它也能够处理动画/多帧JPEG-XL内容。......
  • 离线安装ffmpeg源码包【详细教程】
    今天分享一下ffmpeg源码包的安装过程,针对在没有网络环境下,且不能直接使用yum如何成功安装ffmpeg源码包。博主本人通过正式服务器测试,记录整个安装过程。值得大家收藏同时,我会分享一下如何使用ffmpeg对H.264格式视频(MP4)进行m3u8+ts切片的转换,并生成m3u8+ts格式文件ffmpeg所需要环......
  • FFMPEG 在网络源关闭时保持连接
      FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多code都是从头开发的......
  • 音视频之webRTC和直播
    webrtc是什么Webreal-timecommunication,实时通讯解决方案,涵盖音视频采集、通讯建立、信息传输、音视频显示。怎么做到的音视频采集通过webrtc中MediaStreamAPIgetUserMedia可以获取设备媒体流,包括麦克风、摄像头、屏幕画面等,需要注意兼容性问题。端到端如何音视......
  • 斗鱼直播实现:你主播最爱的Android音视频开发
    一、直播的本质实时推送/拉取音视频数据二、视频直播流程视频直播的流程可以分为如下几步:(1)采集(2)处理(3)编码和封装(4)推流到服务器(5)服务器流分发(6)播放器流播放1、采集视频的采集涉及两方面数据的采集:音频采集和图像采集,它们分别对应两种完全不同的输入源和数据格式。(1)两个传感器:CCD:图像......