我将列出我所知道的所有内容,因为这一切都很重要。
我从亚马逊购买了一个简单的H264流媒体播放器进行测试。特别是这一个:http://www.amazon.com/OPR-NH100-Encoder-Broadcast-Recording-replace/dp/B00NIFJYEC/
设置如下:
如您所见,我正在使用H264的主配置文件。在Apache2中,我通过localhost代理连接。所以在/etc/apache2/sites-enabled/000-default.conf中的Ubuntu我有:
<VirtualHost *:80>
<Proxy "*">
Allow from all
</Proxy>
ProxyPass /hdmi http://192.168.1.168/hdmi retry=0
ProxyPassReverse /hdmi http://192.168.1.168/hdmi
</VirtualHost>
这是相当基本的。从本质上讲,这会绕过任何跨域问题,因为流是本地的。
此时,如果我使用VLC Media Player的网络流查看器打开http://127.0.0.1/hdmi,我可以看到流正常运行。 (我可以播放DVD或流电缆,它们都工作正常)。
然后我尝试将此示例here用于Media Source Extensions。它适用于mp4文件,所以我修改它说:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
</head>
<body>
<video controls></video>
<script>
var video = document.querySelector('video');
var assetURL = 'hdmi';
// Need to be specific for Blink regarding codecs
// ./mp4info frag_bunny.mp4 | grep Codec
var mimeCodec = 'video/mp4; codecs="avc1.4D402A, mp4a.40.2"';
if ('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) {
var mediaSource = new MediaSource;
//console.log(mediaSource.readyState); // closed
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', sourceOpen);
} else {
console.error('Unsupported MIME type or codec: ', mimeCodec);
}
function sourceOpen (_) {
//console.log(this.readyState); // open
var mediaSource = this;
var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
fetchAB(assetURL, function (buf) {
sourceBuffer.addEventListener('updateend', function (_) {
mediaSource.endOfStream();
video.play();
//console.log(mediaSource.readyState); // ended
});
sourceBuffer.appendBuffer(buf);
});
};
function fetchAB (url, cb) {
console.log(url);
var xhr = new XMLHttpRequest;
xhr.open('get', url);
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
cb(xhr.response);
};
xhr.send();
};
</script>
</body>
</html>
在Firefox中,它接受编解码器信息为有效,并与hdmi流建立成功的网络连接。 问题是它没有发挥。当我按下播放没有错误时,它就会旋转。
我想也许编解码器错了。从上面的代码我正在使用:
video/mp4; codecs="avc1.4D402A, mp4a.40.2"
我决定检查以确保这是正确的,所以我跑了:
ffprobe -show_streams http://127.0.0.1/hdmi
Input #0, mpegts, from 'http://127.0.0.1/hdmi':
Duration: N/A, start: 1780.838256, bitrate: 130 kb/s
Program 1
Metadata:
service_name : Service01
service_provider: FFmpeg
Stream #0.0[0x100]: Video: h264 (Main), yuv420p, 1920x1080, 90k tbr, 90k tbn, 180k tbc <--- Main Profile so 4D
Stream #0.1[0x101]: Audio: aac, 48000 Hz, stereo, s16, 130 kb/s
[STREAM]
index=0
codec_name=h264
codec_long_name=H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 <--- AVC so avc1
codec_type=video
codec_time_base=1/180000
codec_tag_string=[27][0][0][0]
codec_tag=0x001b
width=1920
height=1080
has_b_frames=0
pix_fmt=yuv420p
level=42 <-- Level is 42 which is 0x2A
id=0x100
r_frame_rate=180000/2
avg_frame_rate=0/0
time_base=1/90000
start_time=1780.911511
duration=N/A
[/STREAM]
[STREAM]
index=1
codec_name=aac <---- AAC = mp4a
codec_long_name=Advanced Audio Coding
codec_type=audio
codec_time_base=1/48000
codec_tag_string=[15][0][0][0]
codec_tag=0x000f
sample_rate=48000.000000
channels=2
bits_per_sample=0
id=0x101
r_frame_rate=0/0
avg_frame_rate=375/8
time_base=1/90000
start_time=1780.838256
duration=N/A
[/STREAM]
这清楚地表明主要配置文件的使用就像我在流光配置设置中设置的一样。它还显示正在使用的Level 42,我认为它转换为avc1.4D402A,因为我见过的所有主要配置文件示例都使用了4D40,然后2A是十六进制的42。我读错了吗? (我已经尝试了大量其他组合而没有变化)。
音频是AAC所以mp4a是正确的,但我对40.2部分没有信心。我在线阅读了几个例子saying to use mp4file,所以我使用VLC保存原始流然后运行:
mp4file --dump networkhdmi.mp4
但是由于流不是以有效的非delta帧开始,因此它失败了,因为它是一个流。如果您需要测试并查看问题,这是原始流文件:
http://sirisian.com/randomfiles/networkhdmi.mp4
我甚至尝试在浏览器中使用该原始文件运行该文件而不是使用该流,但它失败了。
我开始认为如果第一帧是增量帧,FireFox的MP4解码器不起作用。 ffprobe在分析流时显示:
non-existing PPS referenced
non-existing PPS 1 referenced
decode_slice_header error
no frame!
这会绊倒浏览器吗?似乎VLC并没有受到它的困扰。
我认为networkhdmi.mp4文件是一个非常好的测试用例,因为它正是来自流的内容并且完美地显示了问题。在上面的代码中只需更改:
var assetURL = 'hdmi';
为:
var assetURL = 'networkhdmi.mp4';
以下是我网站上的一个示例:
http://sirisian.com/randomfiles/networkhdmi.html
如果您需要任何其他信息,请在评论中提出,我会提供。我一直在研究这两天而没有任何进展。 (如果有人要求我尝试使用H264高配置文件,它在浏览器中也不起作用。还尝试了可变比特率并尝试了Chrome和Firefox的最新版本。)
我的一位朋友评论道:
浏览器无法使用MSE处理任何流。它需要完全独立的MP4块,就像你从MPEG-DASH流或类似物中获得的那样。 MP4块应该以AAVCS或任何extradata开头,然后是IDR关键帧然后是delta帧
有javascript库将transmux mpeg2-ts转换为mp4,因此它可以由MSE播放;然而,它们都基于HLS,其中.ts文件是单独的块,并且在下载完成时它转换为一个,你将要做的就是自己检测IDR,并停止并转换到目前为止你所拥有的一切并将其提供给MSE,不断。它们都不支持TS的渐进式http下载
这似乎对吗?我尝试使用不适用于此流的HLS。我的朋友提到:
HLS被定义为m3u8,当你有一个连续的TS时,它具有相关的TS fragemnts,因为MSE只接受MP4而MP4不能流式传输
这听起来像是完成这项功能的很多工作。由于我有一个代理,我想我可以尝试将ffmpeg与nginx-rtmp或其他东西一起使用。我要去调查和测试。