- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在尝试编写一个简单的 Windows 媒体基础命令行工具,以使用 IMFSourceReader
和 IMFSyncWriter
加载视频,读取视频和音频作为未压缩的流并使用一些特定的硬编码设置将它们重新编码为 H.246/AAC。
The simple program Gist is here
(注意:我一直在测试的视频都是立体声,48000k 采样率)
该程序可以运行,但在某些情况下,当在编辑程序中将新输出的视频与原始视频进行比较时,我发现复制的视频流匹配,但拷贝的音频流预先固定了一些静音并且音频偏移,这在我的情况下是 Not Acceptable 。
audio samples:
original - |[audio1] [audio2] [audio3] [audio4] [audio5] ... etc
copy - |[silence] [silence] [silence] [audio1] [audio2] [audio3] ... etc
在这种情况下,第一个视频帧的时间戳为非零,但第一个音频帧的时间戳为 0。
我希望能够复制视频和音频流的第一帧为 0 的视频,因此我首先尝试从所有后续视频帧中减去初始时间戳 (videoOffset
)它制作了我想要的视频,但导致了音频的这种情况:
original - |[audio1] [audio2] [audio3] [audio4] [audio5] ... etc
copy - |[audio4] [audio5] [audio6] [audio7] [audio8] ... etc
音轨现在向另一个方向移动了一点,但仍然没有对齐。当视频流的开始时间戳为 0 但 WMF 仍然在开头切断一些音频样本时,有时也会发生这种情况(参见示例视频 3)!
在将音频样本数据传递给 IMFSinkWriter
时,我已经能够修复此同步对齐并偏移视频流以从 0 开始:
//inside read sample while loop
...
// LONGLONG llDuration has the currently read sample duration
// DWORD audioOffset has the global audio offset, starts as 0
// LONGLONG audioFrameTimestamp has the currently read sample timestamp
//add some random amount of silence in intervals of 1024 samples
static bool runOnce{ false };
if (!runOnce)
{
size_t numberOfSilenceBlocks = 1; //how to derive how many I need!? It's aribrary
size_t samples = 1024 * numberOfSilenceBlocks;
audioOffset = samples * 10000000 / audioSamplesPerSecond;
std::vector<uint8_t> silence(samples * audioChannels * bytesPerSample, 0);
WriteAudioBuffer(silence.data(), silence.size(), audioFrameTimeStamp, audioOffset);
runOnce= true;
}
LONGLONG audioTime = audioFrameTimeStamp + audioOffset;
WriteAudioBuffer(dataPtr, dataSize, audioTime, llDuration);
奇怪的是,这会创建一个与原始文件相匹配的输出视频文件。
original - |[audio1] [audio2] [audio3] [audio4] [audio5] ... etc
copy - |[audio1] [audio2] [audio3] [audio4] [audio5] ... etc
解决方案是在音频流的开头插入 block 大小为 1024 的额外静音。 IMFSourceReader
提供的音频 block 大小无关紧要,填充是 1024 的倍数。
我的问题是,静音偏移似乎没有可检测的原因。为什么我需要它?我怎么知道我需要多少?经过数天的解决这个问题后,我偶然发现了 1024 样本静音 block 解决方案。
有些视频似乎只需要 1 个填充 block ,有些需要 2 个或更多,有些根本不需要额外的填充!
我的问题是:
有谁知道为什么会这样?
是不是我在这种情况下错误地使用了 Media Foundation 导致了这种情况?
如果我是正确的,我如何使用视频元数据来确定我是否需要填充音频流以及填充中需要多少 1024 个静音 block ?
编辑:
对于上面的示例视频:
sample video 1 : 视频流从 0 开始并且不需要额外的 block ,原始数据的直通工作正常。
sample video 2 : 视频流从 834166 (hns) 开始,需要 1 1024 block 静默来同步
sample video 3 : 视频流从 0 开始,需要 2 1024 个静音 block 才能同步。
更新:
我尝试过的其他事情:
最佳答案
我写了另一个版本的程序来正确处理 NV12 格式(你的不工作):
EncodeWithSourceReaderSinkWriter
我使用 Blender 作为视频编辑工具。这是我使用 Tuning_against_a_window.mov 的结果:
从下到上:
正如 Roman R. 所说,MediaFoundation mp4 源不使用“edts/elst”原子。但是 Blender 和您的视频编辑工具可以。 mp4 源也会忽略“tmcd”轨道。
“edts/elst”:
Edit lists can be used for hint tracks...
The MPEG-4 file source silently ignores hint tracks.
所以其实编码是好的。与真实的音频/视频数据相比,我认为没有音频流同步偏移。例如,您可以将“edts/elst”添加到编码文件中,以获得相同的结果。
PS:在编码文件中,我为音频/视频轨道添加了“edts/elst”。我还增加了 trak 原子和 moov 原子的大小。我确认,Blender 为原始文件和编码文件显示相同的波形。
编辑
我试图在 3 个视频示例中了解 mvhd/tkhd/mdhd/elst 原子之间的关系。 (是的,我知道,我应该阅读规范。但我很懒...)
您可以使用 mp4 资源管理器工具获取原子的值,或使用我的 H264Dxva2Decoder 项目中的 mp4 解析器:
Tuning_against_a_window.mov
GREEN_SCREEN_ANIMALS__ALPACA.mp4
GOPR6239_1.mov
如您所见,对于 GOPR6239_1.mov,elst 的媒体时间为 0。这就是此文件没有视频/音频同步问题的原因。
对于 Tuning_against_a_window.mov 和 GREEN_SCREEN_ANIMALS__ALPACA.mp4,我尝试计算视频/音频偏移。我修改了我的项目以考虑到这一点:
EncodeWithSourceReaderSinkWriter
目前,我没有找到适用于所有文件的通用计算方法。
我只是找到了正确编码这两个文件所需的视频/音频偏移量。
对于 Tuning_against_a_window.mov,我在(电影时间 - 视频/音频 mdhd 时间)之后开始编码。对于 GREEN_SCREEN_ANIMALS__ALPACA.mp4,我在视频/音频最后一个媒体时间后开始编码。
没关系,但我需要为所有文件找到正确的唯一计算。
所以你有两个选择:
这取决于你的需求:
如果您选择第一个选项,我将解释如何添加第一个原子。
PS:我对这个问题很感兴趣,因为在我的 H264Dxva2Decoder 项目中,edts/elst 原子在我的待办事项列表中。我解析它,但我不使用它...
PS2:这个链接听起来很有趣: Audio Priming - Handling Encoder Delay in AAC
关于c++ - 媒体基础视频重新编码产生音频流同步偏移,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55054531/
我对此很陌生,我在这里的论坛上检查过答案,但我没有找到任何真正可以帮助我的答案。我正在尝试播放 res/raw 文件夹中的视频。到目前为止我已经设置了这段代码: MediaPlayer mp; @Ov
我可以播放一个视频剪辑,检测视频的结尾,然后创建一个表单,然后播放另一个视频剪辑。我的问题是,表单 react 不正确,我创建了带有提交按钮和两个单选按钮可供选择的表单。我希望让用户进行选择,验证响应
首先,我必须说我在web2py讨论组中看到过类似的内容,但我不太理解。 我使用 web2py 设置了一个数据库驱动的网站,其中的条目只是 HTML 文本。其中大多数将包含 img和/或video指向相
我正在尝试在视频 View 中播放 YouTube 视频。 我将 xml 布局如下: 代码是这样的: setContentView(R.layout.webview); VideoV
我正在开发一个需要嵌入其中的 youtube 视频播放器的 android 应用程序。我成功地从 API 获得了 RTSP 视频 URL,但是当我试图在我的 android 视频 View 中加载这个
我目前正在从事一个使用 YouTube API 的网络项目。 我完全不熟悉 API。所以每一行代码都需要付出很多努力。 使用以下代码,我可以成功检索播放列表中的项目: https://www.goog
是否可以仅使用视频 ID 和 key 使用 API V3 删除 youtube 视频?我不断收到有关“必需参数:部分”丢失的错误消息。我用服务器和浏览器 api 键试了一下这是我的代码: // $yo
所以我一直坚持这个大约一个小时左右,我就是无法让它工作。到目前为止,我一直在尝试从字符串中提取整个链接,但现在我觉得只获取视频 ID 可能更容易。 RegEx 需要从以下链接样式中获取 ID/URL,
var app = angular.module('speakout', []).config( function($sceDelegateProvider) {
我正在努力从 RSS 提要中阅读音频、视频新闻。我如何确定该 rss 是用于新闻阅读器还是用于音频或视频? 这是视频源:http://feeds.cbsnews.com/CBSNewsVideo 这是
利用python反转图片/视频 准备:一张图片/一段视频 python库:pillow,moviepy 安装库 ?
我希望在用户双击视频区域时让我的视频全屏显示,而不仅仅是在他们单击控件中的小图标时。有没有办法添加事件或其他东西来控制用户点击视频时发生的情况? 谢谢! 最佳答案 按照 Musa 的建议,附
关闭。这个问题需要更多 focused .它目前不接受答案。 想改进这个问题?更新问题,使其仅关注一个问题 editing this post . 7年前关闭。 Improve this questi
我有一个公司培训视频加载到本地服务器上。我正在使用 HTML5 的视频播放来观看这些视频。该服务器无法访问网络,但我已加载 apache 并且端口 8080 对同一网络上的所有机器开放。 这些文件位于
我想混合来自 video.mp4 的视频(时长 1 分钟)和来自 audio.mp3 的音频(10 分钟持续时间)到一个持续时间为 1 分钟的输出文件中。来自 audio.mp3 的音频应该是从 4
关闭。这个问题需要更多 focused .它目前不接受答案。 想改进这个问题?更新问题,使其仅关注一个问题 editing this post . 8年前关闭。 Improve this questi
我正在尝试使用 peer/getUserMedia 创建一个视频 session 网络应用程序。 目前,当我将唯一 ID 发送到视频 session 时,我能够听到/看到任何加入我的 session
考虑到一段时间内的观看次数,我正在评估一种针对半自动脚本的不同方法,该脚本将对视频元数据执行操作。 简而言之,只要视频达到指标中的某个阈值,就说观看次数,它将触发某些操作。 现在要执行此操作,我将不得
我正在通过iBooks创建专门为iPad创建动态ePub电子书的网站。 它需要支持youtube视频播放,所以当我知道视频的直接路径时,我正在使用html5 标记。 有没有一种使用html5 标签嵌入
我对Android不熟悉,我想浏览youtube.com并在Webview内从网站显示视频。当前,当我尝试执行此操作时,将出现设备的浏览器,并让我使用设备浏览器浏览该站点。如果Webview不具备这种
我是一名优秀的程序员,十分优秀!