音频计量与LibVLC
Audio Metering with LibVLC
我在Windows c++应用程序中使用LibVLC来显示视频流。
我想监视传入的音频样本,以生成传递到应用程序的另一部分的计量数据。我有这种类型的libvlc_audio_set_callbacks
工作,除了a:我正在监控输出音频,所以它受到静音等的影响,b:当我启用此功能时,无法听到音频(不可否认,这是文档中描述的行为)。
是否有一种方法实际做到这一点与LibVLC API,或者我需要写一个音频过滤器插件?
或者,是否有一些现有的通用"音频嗅探"插件,我可以使用?
现在回复有点晚了,但这是一个我很难解决的问题,其他人可能也在同样的地方(即使OP早就搬走了!)
关键是使用smem
插件。这可以让你在播放时跟踪音频和视频(有一些严肃的警告,见下文)。为了在同一时间玩和计量,你需要duplicate
流(分裂它)。下面是要使用的输出字符串:
std::ostringstream outstream;
outstream << ":sout=#duplicate{dst=std{access=file,dst="" << filepath << ""},dst="transcode{acodec=s16l}:" << createFrameCallbackString(true) << ""}";
libvlc_media_add_option(media, outstream.str().c_str());
我们需要创建一个输出链,其中流被分割,因此调用duplicate
。在duplicate中,有两个目标。
outstream << ":sout=#duplicate{dst=...,dst=...}";
在我的例子中,我记录到文件(而不是显示到视频窗口),所以你会想用你自己的第一个目的地替换。第二个目的地是我们使用smem
将音频(和/或视频)发送到回调方法的地方:
"..., dst="transcode{acodec=s16l}:" << createFrameCallbackString(true) << ""}"
注意smem中的音频,它必须在PCM中(或从文档中看来),因此我们将其转码为带符号的16位小端序(s16l)(这是末尾的L,而不是1)。转码的间接成本是多少?在我的测试中,它似乎非常小,但如果您担心性能问题,它值得一看。
配置smem的输出链如下:
class Player
{
//callback for frame monitoring
static void prerendercb(void *data, unsigned char** buffer, size_t size)
{
//we must allocate a buffer in order for postrender to be called
*buffer = (uint8_t *)malloc(size);
}
static void postrendercb(void *data, unsigned char* buffer, int width, int height, int pitch, size_t size, int64_t pts)
{
Player* context = (Player*)data;
//free the buffer
free(buffer);
//notify context of frame for processing
context->OnFrame(/*pass it whatever information you need*/);
}
static void audio_prerendercb(void* data, unsigned char** buffer, size_t size)
{
*buffer = (uint8_t *)malloc(size);
}
static void audio_postrendercb(void* data, unsigned char* buffer, unsigned int channels, unsigned int rate,
unsigned int nb_samples, unsigned int bits_per_sample, size_t size, int64_t pts)
{
Player* context = (Player*)data;
//free the buffer
free(buffer);
//notify context
context->OnAudioFrame(/*whatever data is needed*/);
}
//Get an smem string for the audio/video callbacks
std::string Player::createFrameCallbackString(bool timesync) const
{
std::ostringstream text;
text <<
"smem{" << "video-prerender-callback=" << ((long long int)(intptr_t)(void*)&prerendercb) << "," <<
"video-postrender-callback=" << ((long long int)(intptr_t)(void*)&postrendercb) << "," <<
"video-data=" << ((long long int)(intptr_t)(void*)this) << "," <<
"audio-prerender-callback=" << ((long long int)(intptr_t)(void*)&audio_prerendercb) << "," <<
"audio-postrender-callback=" << ((long long int)(intptr_t)(void*)&audio_postrendercb) << "," <<
"audio-data=" << ((long long int)(intptr_t)(void*)this) << "," <<
"time-sync=" << (timesync ? "1" : "0") <<
"}";
return text.str();
}
}
警告
除了转码问题,以及无论您是否关心它都必须分配缓冲区数据的事实之外,最大的问题是libVLC异步处理帧。因此,你可能会看到10到15帧的画面同时被处理,然后一段时间内你看不到任何东西,然后是另一个画面。这肯定受到缓存大小的影响(libVLC中有几个),但即使将缓存大小设置得尽可能低,你仍然会得到至少2或3帧的爆发。设置这些选项很有帮助:
libvlc_media_add_option(media, ":clock-synchro=0"); //this setting is critical for realtime processing of audio stream!
libvlc_media_add_option(media, ":clock-jitter=0");
构造输出链时的另一个警告是注意引号和括号。可能会有一些指导方针,但对我来说,这是一个尝试和错误。
最后,在smem
中使用time-sync
选项时,我从未注意到合理的差异。我确信它的设置很重要,但我无法确定如何设置。
我在使用libVLC时发现它并不是为这种用途而设计的。它可以扭曲成可用的形状,但它永远不会像它应该的那样表现得很好。它是开源的,所以喜欢冒险的人可以通过修改源代码来制定一个更有效的解决方案。
- 用c++阅读音频
- 为什么这个音频包络不能通过开关的情况?
- FFMpeg库:如何在音频文件中精确查找
- 需要反转音频步进公式
- 如何在音频处理中使用超能力时间拉伸类
- C++新手,想知道如何使用VS code 2019播放音频文件
- 如何暂停插孔音频客户端
- 如何以编程方式将音频从任何录制设备路由到任何播放设备
- 将音频从浏览器流式传输到WebRTC本机C++应用程序
- 使用IMFSourceReader(Microsoft媒体基金会)进行音频流传输
- 大声音频无法播放
- 让 iaxClient 将音频发送到缓冲区而不是音频设备/从缓冲区获取音频
- 适用于 macOS 的 Xcode 应用程序。这就是我设置从USB麦克风输入获取音频的方式。一年前工作,现在没有了。为什么
- 波形音频 - waveOutWrite 发出断断续续的声音
- WASAPI 共享模式:音频引擎预期的振幅是多少?
- 在Win7上,在默认端点上轮询音频会话有时会崩溃
- 媒体基金会:WavSink以比实时消耗率更快的速度处理音频-是否可以实时限制后台处理
- PJSUA在两个或多个不同的音频声卡之间切换
- 如何使用libvlc API或FFmpeg API提取音频/视频剪辑
- 音频计量与LibVLC