如果你对开源项目、提升技术、副业、面试、历史、八卦等等感兴趣的,可以加我微信 yunmz777,刚好我们有这样的交流群.
在直播中,连麦功能允许主播与观众或者其他主播进行实时互动,这种互动通常是通过视频或音频完成的。屏幕分屏效果是连麦中的一个重要视觉效果,它允许观众同时看到多个参与者。这种效果不仅增加了直播的互动性,还丰富了观众的观看体验。
屏幕分屏效果通常有几种不同的布局方式:
-
平分屏幕:这是最常见的分屏方式,屏幕被平均分成两部分,每个参与者占据一半的屏幕空间。这种方式适用于两个参与者的连麦。
-
画中画:在这种布局中,主播的视频画面占据大部分屏幕空间,而连麦的观众或另一个主播的画面则较小,通常出现在屏幕的一角。这种方式允许主画面保持观众的主要注意力,同时也可以看到连麦参与者的反应。
-
多分屏:当直播中有多于两个的参与者连麦时,屏幕会被分成多个小画面,每个参与者都有自己的一块区域。这种布局方式适用于团队讨论、多人游戏等场景。
-
动态切换:在一些直播平台或软件中,系统可以根据谁在说话来动态切换显示的画面。虽然这种方式在技术上更为复杂,但它能确保观众总是看到当前活跃的讲话者,从而提高直播的参与感和互动性。
那么在接下来的内容中,我们将使用 ffmpeg 实现平分屏幕的效果,也就是说将两个视频合并到一起。
视频高度相同的情况下
视频靠度的相同就是说我们同一台相机拍摄出来的,且都是横拍的那种,除此之外,编码和分辨率都是相同的。
要执行这些命令之前,我们首先要对安装 ffmpeg
js
const { spawn } = require("child_process");
const ffmpegCommand = "ffmpeg";
const args = [
"-i",
"./m.mp4",
"-i",
"./n.mp4",
"-filter_complex",
"[0:v][1:v]hstack=inputs=2[v]",
"-map",
"[v]",
"./output.mp4",
];
const process = spawn(ffmpegCommand, args);
process.stdout.on("data", (data) => {
console.log(`stdout: ${data}`);
});
process.stderr.on("data", (data) => {
console.error(`stderr: ${data}`);
});
process.on("close", (code) => {
console.log(`child process exited with code ${code}`);
});
在上面的这段代码中,我们是直接使用了 Node.js 的 child_process 模块来执行 ffmpeg 命令来实现将两个视频文件并排合并成一个新的视频文件。
接下来分别了解一下之后的这些参数都分别代表什么:
-
i ./m.mp4
:指定输入文件1
,./m.mp4
。 -
-filter_complex "[0:v][1:v]hstack=inputs=2[v]"
:这是一个复杂过滤器的表达式,用于处理和生成新的视频流。[0:v][1:v]
表示选择第一个和第二个输入文件的视频流。hstack=inputs=2
将这两个视频流并排(水平堆叠)组合成一个视频流。[v]是这个新视频流的标签。 -
-map "[v]"
:这个选项用来选择特定的视频流作为输出。在这个例子中,它选择了上面通过 filter_complex 生成的并排视频流。
而最终输出文件的路径和名称为 ./output.mp4
这是我们提前准备好的两个文件,如下图所示:
最终的结果输出了这样的文件内容:
上面的代码,要想将上述的代码中使用的 ffmpeg 命令转换为可以直接在 bash 或终端中执行的命令,你只需要使用 ffmpeg 命令行工具,并应用相同的参数:
bash
ffmpeg -i ./m.mp4 -i ./n.mp4 -filter_complex "[0:v][1:v]hstack=inputs=2[v]" -map "[v]" ./output.mp4
视频高度不同的情况下
当使用 ffmpeg 合并两个分辨率和编码不同的视频时报错,通常是因为这些差异导致 ffmpeg 无法直接将视频流合并到一起。具体来说,可能存在以下问题:
-
分辨率不一致:当你使用 hstack(水平堆叠)或 vstack(垂直堆叠)等滤镜进行视频合并时,所有视频流需要具有相同的分辨率。如果分辨率不同,ffmpeg 无法对它们进行直接堆叠。
-
编码格式不同:虽然不同的编码格式不会直接阻止合并过程,但在最终输出之前,可能需要对视频进行重编码以确保兼容性。如果没有指定合适的编码设置,可能会导致错误或合并后的视频无法正确播放。
要解决这些问题,你可以在合并之前对视频进行预处理,以确保它们具有一致的分辨率和兼容的编码设置。因此我们可以使用 ffmpeg 的 scale 滤镜调整视频的分辨率。
首先我们接下来使用到的是这两个视频,如下:
js
const { spawn } = require("child_process");
const ffmpegCommand = "ffmpeg";
const args = [
"-i",
"./mm.mp4",
"-i",
"./nn.mp4",
"-filter_complex",
`[0:v]scale=-2:540[video1]; [1:v]scale=-2:540[video2]; [video1][video2]hstack=inputs=2[video]; [0:a][1:a]amix=inputs=2[audio]`,
"-map",
"[video]",
"-map",
"[audio]",
"./mmm.mp4",
];
const process = spawn(ffmpegCommand, args);
process.stdout.on("data", (data) => {
console.log(`stdout: ${data}`);
});
process.stderr.on("data", (data) => {
console.error(`stderr: ${data}`);
});
process.on("close", (code) => {
console.log(`子进程以代码 ${code} 退出`);
});
在上面的这个代码中,我们主要对几个核心的参数来进行讲解:
-
过滤器复杂操作(-filter_complex):
-
[0:v]scale=-2:540[video1]; [1:v]scale=-2:540[video2];:这部分将第一个([0:v])和第二个([1:v])视频的分辨率调整为宽度自动适应、高度为 540 像素,并分别标记为[video1]和[video2]。
-
[video1][video2]hstack=inputs=2[video];:将调整分辨率后的两个视频水平堆叠成一个视频流,并标记为[video]。
-
[0:a][1:a]amix=inputs=2[audio]:将两个视频的音频流混合成一个音频流,并标记为[audio]。
-
-
映射输出流(-map):
map "[video]"
和-map "[audio]"
这些选项指定了 ffmpeg 应该使用哪些处理过的流作为最终输出的视频和音频流。
除了使用脚本来执行之外,我们还是可以使用 bash 命令来执行的,如下:
bash
ffmpeg -i ./mm.mp4 -i ./nn.mp4 \
-filter_complex "[0:v]scale=-2:540[video1]; [1:v]scale=-2:540[video2]; [video1][video2]hstack=inputs=2[video]; [0:a][1:a]amix=inputs=2[audio]" \
-map "[video]" -map "[audio]" ./mmm.mp4
剩下的那些就是我们之前降到的了,接下来我们看看效果:
现在这样子就实现我们标题中说的直播连麦 pk 的效果了。
总结
通过 ffmpeg 我们可以搞到很多很有趣的东西,别的不说,我写这个文章的时候看到这个视频就一直在笑,可能是我笑点低吧哈哈哈哈哈。
最后分享两个我的两个开源项目,它们分别是:
这两个项目都会一直维护的,如果你也喜欢,欢迎 star 🚗🚗🚗