又双叒叕打不开了
录完一节课,拖进PR------报错。发给学员------黑屏。换PotPlayer------无法渲染。
右键一看属性:H.265/HEVC。
好家伙,文件是录出来了,但没人打得开。
这篇文章把这个坑填了。从原理到代码到工具,一次性讲透。
一、先搞懂:H.264 vs H.265 差在哪
一句话:H.265更小,但更挑设备。
| H.264 | H.265 | |
|---|---|---|
| 兼容性 | ✅ 全平台通吃 | ❌ 老设备/旧软件大概率翻车 |
| 同画质体积 | 基准 | 小30%~50% |
| 适用 | 通用分发 | 存储敏感场景 |
⚠️ 注意:.mp4 是容器,不是编码。里面装的什么才决定能不能播。
二、4种实战方案(代码可直接跑)
方案① FFmpeg一行命令转码
最快,不想写代码就用这个:
r
bash
ffmpeg -i input_h265.mp4 -c:v libx264 -preset ultrafast -crf 18 -c:a aac output_h264.mp4
要点 :-crf 18 高质量档,-preset ultrafast 速度优先。转完体积涨40%左右,但全兼容。
方案② Python + mss + FFmpeg管道(录制直出H.264)
录制时直接写H.264,跳过H.265:
python
python
import cv2, numpy as np, subprocess, mss
from datetime import datetime
sct = mss.mss()
monitor = sct.monitors
out = f"rec_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4"
cmd = [
'ffmpeg', '-y',
'-f', 'rawvideo', '-vcodec', 'rawvideo',
'-s', f"{monitor['width']}x{monitor['height']}",
'-pix_fmt', 'bgr24', '-r', '30', '-i', '-',
'-c:v', 'libx264', '-preset', 'ultrafast', '-crf', '18',
'-c:a', 'aac', '-b:a', '192k', out
]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
try:
while True:
frame = cv2.cvtColor(np.array(sct.grab(monitor)), cv2.COLOR_BGRA2BGR)
p.stdin.write(frame.tobytes())
except KeyboardInterrupt:
p.stdin.close(); p.wait()
CPU占用8%~12%,可在frame处理处加水印、缩放。
方案③ Python + dxcam(GPU硬加速60fps)
录游戏/高帧率场景,GPU直取不掉帧:
python
python
import dxcam, subprocess, numpy as np
from datetime import datetime
cam = dxcam.create(output_idx=0, output_color="BGR")
out = f"game_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4"
cmd = [
'ffmpeg', '-y',
'-f', 'rawvideo', '-vcodec', 'rawvideo',
'-s', '1920x1080', '-pix_fmt', 'bgr24', '-r', '60', '-i', '-',
'-c:v', 'libx264', '-preset', 'ultrafast', '-crf', '18', out
]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
try:
while True:
f = cam.get_latest_frame()
if f is not None:
p.stdin.write(f.tobytes())
except KeyboardInterrupt:
p.stdin.close(); p.wait(); cam.stop()
实测1080P 60fps,CPU仅5%~8%。
方案④ 音画同步双管道
解决最头疼的音画不同步:
scss
python
import dxcam, subprocess, sounddevice as sd, numpy as np
from datetime import datetime
fs, buf = 48000, []
def cb(d, f, t, s): buf.append(d.copy())
cam = dxcam.create(output_idx=0, output_color="BGR")
out = f"sync_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4"
cmd = [
'ffmpeg', '-y',
'-f', 'rawvideo', '-vcodec', 'rawvideo',
'-s', '1920x1080', '-pix_fmt', 'bgr24', '-r', '30', '-i', '-',
'-f', 's16le', '-acodec', 'pcm_s16le', '-ar', str(fs), '-ac', '1', '-i', '-',
'-c:v', 'libx264', '-preset', 'ultrafast', '-crf', '18',
'-c:a', 'aac', '-b:a', '192k', out
]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
sd.InputStream(samplerate=fs, channels=1, callback=cb).start()
try:
while True:
f = cam.get_latest_frame()
if f is not None:
p.stdin.write(f.tobytes())
if len(buf) >= fs // 30:
p.stdin.write(np.concatenate(buf).tobytes()); buf.clear()
except KeyboardInterrupt:
sd.stop(); p.stdin.close(); p.wait(); cam.stop()
H.264 + AAC 双管齐下,任意播放器通吃。
三、不想写代码?图形工具也能搞定
以嗨格式录屏大师为例,逻辑很简单:
- 编码前置锁定:选"设备适配"档位,自动输出H.264,不给你碰H.265的机会
- DXGI硬加速:GPU直取60帧,录游戏不掉帧
- 音画同步+实时标注:系统音/麦克风双轨采集,录制中直接画笔圈重点
本质就是把上面的Python链路做成了GUI,适合不折腾的同学。
四、FAQ
Q:转完文件太大?
调高-crf到22~28,或降分辨率到1280×720。
Q:转码画质糊了?
有损转码必有损失。源头直接录H.264才是正解。
Q:音画不同步?
用WASAPI Loopback采系统音,或FFmpeg加-itsoffset补偿。
Q:手机打不开?
先看编码是不是H.265,是就转H.264;不是就是文件截断,重新导出。
总结
表格
| 策略 | 一句话 |
|---|---|
| 编码前置 | 录的时候就选H.264,最省事 |
| 掌握FFmpeg | 转码/管道录制的万能钥匙 |
| 参数平衡 | CRF+分辨率+帧率,铁三角动态调 |
| 标准流程 | 录制→查编码→转码→验证→分发 |
把兼容性思维放到录制那一步,比事后反复转码强一百倍。