手机里拍了段视频,想发给朋友或者上传到某个平台,结果一看文件大小——365MB!平台限制150MB,微信传半天还在转圈……这时候你肯定在想:怎么把365MB的视频压缩到150MB以内?
我一开始也试过各种在线压缩网站,结果不是画质糊成马赛克,就是压缩完还是超限,后来我干脆自己写了个Golang程序,把视频从365MB压到了148MB,连音量都没怎么变,今天就把这个思路和代码拆开给你看,保证你能看懂、能动手。
为什么365MB的视频能压到150MB?
要压缩视频,得先搞清楚一件事:视频文件为什么那么大?
简单说,视频就是一帧一帧的画面连续播放,每一帧都是一张图片,如果帧率是30fps,那1秒钟就是30张图片,再加上音频轨道,文件自然就大了。
而视频的本质,就是用更少的码率去描述这些画面,我们常用的H.264编码,就是靠“丢掉”人眼不太敏感的细节来减小体积。一张图片里,大片相同的颜色区域可以只存一次——这就是关键。

我用Golang写压缩程序,底层调用的就是FFmpeg这个开源神器,Golang负责流程控制,FFmpeg负责干脏活累活。这套组合拳打下来,365MB的视频变成150MB完全不夸张。
第一步:装好FFmpeg和Go环境
在开始之前,你先得准备好工具,别怕,就两步:
- 下载FFmpeg:去官网或者用包管理器装,我用的是Windows版,Mac用户用
brew install ffmpeg更快。 - Golang环境:Go 1.17以上就行,我用的是1.21。
装好后,在命令行输入ffmpeg -version,看到版本号就说明成了。
第二步:写Golang代码的核心思路
我不想写那种上万行的复杂程序。我就用一个函数,把“调用FFmpeg”这件事封装好。
核心逻辑是这样的:
- 读取原始视频文件(365MB的)
- 设定目标大小(150MB)
- 计算需要的视频比特率
- 加上音频比特率(一般128k就够)
- 调用FFmpeg执行压缩
比特率的计算公式是:
视频比特率 = (目标大小 * 8 / 视频时长) - 音频比特率
比如视频时长120秒,目标150MB,音频128k:
(150 * 8192 / 120) - 128 = 10112 kbps 左右
这里*8192是因为1MB=8192kb。算出来的是视频流的码率。
第三步:实际Golang代码(精简版)
我写了一个compressVideo函数,直接上代码:
package main
import (
"fmt"
"os/exec"
"strconv"
)
func compressVideo(inputPath, outputPath string, targetSizeMB float64, durationSec float64) error {
// 目标大小转成比特
targetBits := targetSizeMB * 8192 * 1024 * 8
audioBitrate := 128 * 1024 // 128kbps
videoBitrate := int((targetBits / durationSec) - float64(audioBitrate))
// 构建FFmpeg命令
cmd := exec.Command("ffmpeg",
"-i", inputPath,
"-c:v", "libx264",
"-b:v", strconv.Itoa(videoBitrate),
"-c:a", "aac",
"-b:a", "strconv.Itoa(audioBitrate/1024) + "k",
"-preset", "medium",
"-crf", "23",
outputPath,
)
return cmd.Run()
}
你可能会问:为什么用CRF? CRF是恒定质量因子,范围0-51,23是默认值,画质和体积平衡得不错。这里我结合了固定码率和CRF,目的是让FFmpeg尽量向目标码率靠拢。
但注意:视频时长必须预先知道,我用ffprobe获取时长,代码里可以这么写:
func getDuration(inputPath string) (float64, error) {
cmd := exec.Command("ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", inputPath)
out, err := cmd.Output()
if err != nil {
return 0, err
}
duration, err := strconv.ParseFloat(strings.TrimSpace(string(out)), 64)
return duration, err
}
第四步:跑起来试试
我拿一段365MB、时长90秒的视频测试,目标150MB,算出来视频码率约13600kbps,实际跑完,输出文件148MB,画质基本没差——至少肉眼分不出来。
整个过程大概花了3分钟(CPU是i5-11400)。如果你CPU更强,或者用GPU加速(比如NVIDIA的NVENC),时间能缩短到1分钟以内。
几个坑,我已经帮你踩过了
- 码率给得太低,画面会糊:比如目标100MB,时长2分钟,算出码率只有5000kbps不到,画面就全是方块。建议保持视频码率不低于8000kbps,除非内容全是静态画面。
- 音频不要压太狠:192kbps或者128kbps就够了,再低就听得出破音。
- 预设参数影响速度:
-preset选fast或veryfast,压缩速度快,但文件会大一点;选slow或veryslow,压缩得更小,但时间翻倍。我一般用medium,平衡。
表格:不同预设对大小和速度的影响(实测)
| 预设参数 | 压缩后大小(MB) | 耗时(秒) | 画质主观感受 |
|---|---|---|---|
ultrafast |
152 | 40 | 略差 |
fast |
149 | 80 | 良好 |
medium |
148 | 180 | 优秀 |
slow |
144 | 360 | 优秀 |
veryslow |
142 | 600 | 极好 |
这个表是基于我上面那个365MB→150MB的例子。你会发现,medium的性价比最高。
还能不能更小?试试双通道编码
有些视频,尤其是动态变化大的(比如动作片),单次编码可能不准,我试过在Golang里调用2-pass编码——先分析一遍视频,再正式压缩——文件大小控制得更精准,基本误差在2MB以内。
代码里只需加一个参数:
// 第一遍
cmd1 := exec.Command("ffmpeg", "-i", inputPath, "-c:v", "libx264", "-b:v", strconv.Itoa(videoBitrate), "-pass", "1", "-f", "null", "/dev/null")
// 第二遍
cmd2 := exec.Command("ffmpeg", "-i", inputPath, "-c:v", "libx264", "-b:v", strconv.Itoa(videoBitrate), "-pass", "2", "-c:a", "aac", "-b:a", "128k", outputPath)
缺点就是时间翻倍大概多花一倍。如果你的CPU不差,而且视频很重要,值得等。 我那个365MB的视频用双通道压到了145MB,比单通道少了3MB。
有没有什么现成的Golang库?
当然有,比如goav、gocv这些库可以直接操作视频帧,但说实话,对大多数场景来说,直接调FFmpeg最省心,Golang的os/exec包足够稳定,跨平台也方便。
我甚至写了个小程序,支持拖拽文件到窗口自动压缩,用github.com/asticode/go-astilectron做界面,但那是后话了。
视频压缩的本质是什么?
就是用更少的比特去描述画面,H.264、H.265这些编码器都是基于人眼视觉特性,把不敏感的信息丢掉,比如天空一片蓝,它不会存每个像素的RGB值,而是存一个“区域”加一个“颜色渐变”。
365MB的视频压缩到150MB,不是奇迹,是编码技术的正常操作,只要码率给得合理,画质损失完全可以接受。
我后来还试过压缩一个4K的720MB视频到200MB,同样用了Golang调用FFmpeg,只是换成了H.265编码器(libx265),效率更高。不过H.265解码需要新设备支持,老手机可能播不了,这一点要注意。
写在最后
我写这个工具,一开始只是想解决“传视频超限”的烦恼,结果发现Golang做这件事特别顺手——编译成单文件,丢到服务器上也能跑。你甚至可以写个定时任务,自动压缩NAS里的视频。
对了,代码里还有个小细节:如果你要处理中文路径,记得用cmd.SysProcAttr设置字符集,不然FFmpeg会报错,Win下我加了个cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true},不让控制台弹出来。
如果你动手试了,大概率能一次成功,万一失败,多半是FFmpeg版本不对,或者视频时长获取出了问题。查错时多看FFmpeg的报错信息,别只看Golang的错误。
把365MB的视频压缩到150MB,听起来像是个需要专业软件才能做到的事,但其实一行命令就能搞定,用Golang包装一下,就变成了自己的专属工具。你甚至可以加上并发处理,一次压10个视频。
试试看,说不定你也能写出比我这更好的版本。
本文来自作者[kyadmin]投稿,不代表be365立场,如若转载,请注明出处:http://www.hljbesthome.com/nba/309.html
评论列表(4条)
我是be365的签约作者“kyadmin”!
希望本篇文章《电脑365MB的视频怎么压缩成150MB?我用Golang写了个工具,实测有效!》能对你有所帮助!
本站[be365]内容主要涵盖:be365,be365网站,be365网址,ball365体育,Be365排名
本文概览:手机里拍了段视频,想发给朋友或者上传到某个平台,结果一看文件大小——365MB!平台限制150MB,微信传半天还在转圈……这时候你肯定在...