提高视频帧率

This commit is contained in:
2025-10-02 15:51:00 +08:00
parent c1e116f65d
commit f4418b8860

View File

@@ -41,7 +41,11 @@ import java.util.Collections;
import java.util.UUID;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.BufferedImage;
import java.awt.Image;
import static org.bytedeco.opencv.global.opencv_core.CV_8UC3;
@@ -342,19 +346,49 @@ public class MediaTransferFlvByJavacv extends MediaTransfer implements Runnable
return;
}
// 优化:跳帧处理,只推送 1/3 的帧25fps -> 8.3fps,如果还慢可改为 %3
// 如果帧率太低,可以改为 % 2推送 50% 帧);如果还是慢,保持 % 3推送 33% 帧)
if (totalFrames % 3 != 0) {
droppedFrames++;
return;
}
if (totalFrames == 1) {
log.info("📤 开始推流到客户端,客户端数量: {}", contexts.size());
}
try {
// 转换为JPEG字节
// 转换为JPEG字节(优化:降低质量和分辨率以提高帧率)
BufferedImage bufferedImage = toImage.convert(frame);
if (bufferedImage == null) {
return;
}
// 优化1降低分辨率缩小到60%,更快)
int targetWidth = (int) (bufferedImage.getWidth() * 0.6);
int targetHeight = (int) (bufferedImage.getHeight() * 0.6);
BufferedImage scaledImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
// 使用快速缩放Graphics2D
java.awt.Graphics2D g2d = scaledImage.createGraphics();
g2d.setRenderingHint(java.awt.RenderingHints.KEY_INTERPOLATION,
java.awt.RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); // 最快
g2d.drawImage(bufferedImage, 0, 0, targetWidth, targetHeight, null);
g2d.dispose();
// 优化2使用低质量 JPEG 编码(质量 0.5,速度快很多)
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "jpg", outputStream);
ImageWriter jpegWriter = ImageIO.getImageWritersByFormatName("jpeg").next();
ImageWriteParam jpegParams = jpegWriter.getDefaultWriteParam();
jpegParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
jpegParams.setCompressionQuality(0.5f); // 质量 50%(默认 75-90%
ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream(outputStream);
jpegWriter.setOutput(imageOutputStream);
jpegWriter.write(null, new javax.imageio.IIOImage(scaledImage, null, null), jpegParams);
jpegWriter.dispose();
imageOutputStream.close();
byte[] imageBytes = outputStream.toByteArray();
// 每1000帧输出一次统计