Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ffmpeg 在碎片化的实时MP4流中发送定期元数据?_Ffmpeg_Mp4_Live Streaming - Fatal编程技术网

Ffmpeg 在碎片化的实时MP4流中发送定期元数据?

Ffmpeg 在碎片化的实时MP4流中发送定期元数据?,ffmpeg,mp4,live-streaming,Ffmpeg,Mp4,Live Streaming,正如主题所建议的,我想知道是否有可能在一个片段化的MP4实时流中定期发送关于流内容的元数据 我正在使用以下命令(1)获取碎片化MP4: ffmpeg -i rtsp://admin:12345@192.168.0.157 -c:v copy -an -movflags empty_moov+omit_tfhd_offset+frag_keyframe+default_base_moof -f mp4 ... 我的主程序从stdout或(unix域)套接字读取此命令的片段,并获取: ftyp m

正如主题所建议的,我想知道是否有可能在一个片段化的MP4实时流中定期发送关于流内容的元数据

我正在使用以下命令(1)获取碎片化MP4:

ffmpeg -i rtsp://admin:12345@192.168.0.157 -c:v copy -an -movflags empty_moov+omit_tfhd_offset+frag_keyframe+default_base_moof -f mp4 ...
我的主程序从stdout或(unix域)套接字读取此命令的片段,并获取:

ftyp
moov
moof
mdat
moof
mdat
moof
mdat 
...
因此,我得到的第一个片段是ftypmoov,它们是元数据并描述流内容

现在,客户端程序稍后会连接到主程序。问题是,到那时,ftypemoov片段早已消失

是否有一种方法(=ffmpeg命令选项)使此工作类似于MPEGTS(也称为mpeg传输流),并定期随流重新发送元数据?像这样:

ftyp
moov
moof
mdat
moof
mdat
moof
mdat 
ftyp
moov
moof
mdat
moof
mdat
moof
mdat 
...
。。或者,我唯一的选择是在我的主程序中缓存ftypmoov数据包,并在请求流时将它们重新发送到客户端程序

相关链接:

每次新客户端连接时,缓存和重新发送ftypmoov也不是那么简单。。因为它以某种方式中断了流(至少浏览器MSE扩展不喜欢这样的流)。在moof数据包中似乎有很多序列号和内容需要修改(+)

另一个选项是通过另一个FFmpeg进程传递流,该进程执行重新移动(并纠正moof数据包)。由于命令(1)没有给出清晰分离的ftypmoovmoof等数据包,事情变得更加复杂

任何想法/解决方案都值得赞赏


编辑:关于(+),MSE在播放带有间隙的分段MP4时似乎存在问题:

ftyp/moov形成了所谓的“初始化片段”,只有在更改流时才应写入MSE。这通常是通过在清单中包含init的URL来处理的,玩家的任务是在加入流时请求它

我终于能够毫无问题地将碎片化的MP4提供给浏览器MSE扩展

如果开始向MSE扩展提供moofmdat数据包,这些数据包不是紧跟在原始ftypmoov之后,则

。。进入MSE扩展的第一个moof数据包必须是一个moof数据包,该数据包具有称为第一个样本标志预设集的特殊标志(有关更多信息,请参阅ISO/IEC 14496-12:2012(E)规范)

。。否则,所有流行浏览器中的MSE都会冻结,并且没有视频播放(顺便说一句,moof从>1开始的序列号根本没有问题)

此python包对于分析非常有用:

为了选择这个标志,在这个答案中提供了客户端javascript函数

使用函数getBox查找框的类型(ftypmoovmoof等)

对于moof框,应用函数findFirstSampleFlag查看moof框是否启用了第一个样本标志预设

函数toInt(arr,index){//从字节到大端32位整数。输入:Uint8Array,index
var dv=新数据视图(arr.buffer,0);
返回dv.getInt32(index,false);//big-endian
}
函数toString(arr,fr,to){//从字节到字符串。输入:Uint8Array,start index,stop index。
返回String.fromCharCode.apply(null,arr.slice(fr,to));
}
函数getBox(arr,i){//输入Uint8Array,开始索引
返回[toInt(arr,i),toString(arr,i+4,i+8)]
}
函数getSubBox(arr,box_name){//input Uint8Array,box name
var i=0;
res=getBox(arr,i);
main_length=res[0];name=res[1];//此框包含长度和名称
i=i+8;
变量子框=空;
而(i
您好,谢谢您的回复。你能更详细地解释一下“在清单中包含init的URL”是什么意思吗?它记录在rfc 8216中。我有点困惑。。我实际上是通过websockets将碎片化的MP4发送到浏览器。我不确定在播放列表中我应该在哪里/如何混合。。任何指向初级读物的链接如果你在做一些非标准的事情,就没有初级读物。但您所做的与flv/rtmp类似,在connect上,您发送一次序列头(init),然后开始发送片段。是的,就是这样。我通过websockets发送低延迟实时视频。我不会创建一个清单,告诉浏览器在哪里下载媒体片段。问题是,缓存ftyp和moov并在稍后及时发送它们,会以某种方式创建一个MSE不喜欢的中断流。如果你知道,你的代码让我去写。在我的例子中,我只在MP4内部广播音频,即使第一个MOOF数据包也始终具有TRUN flags=1(与所有下一个数据包相同)。我在WebSocket服务中必须做的事情
function toInt(arr, index) { // From bytes to big-endian 32-bit integer.  Input: Uint8Array, index
    var dv = new DataView(arr.buffer, 0);
    return dv.getInt32(index, false); // big endian
}

function toString(arr, fr, to) { // From bytes to string.  Input: Uint8Array, start index, stop index.
    return String.fromCharCode.apply(null, arr.slice(fr,to));
}

function getBox(arr, i) { // input Uint8Array, start index
    return [toInt(arr, i), toString(arr, i+4, i+8)]
}

function getSubBox(arr, box_name) { // input Uint8Array, box name
    var i = 0;
    res = getBox(arr, i);
    main_length = res[0]; name = res[1]; // this boxes length and name
    i = i + 8;

    var sub_box = null;

    while (i < main_length) {
        res = getBox(arr, i);
        l = res[0]; name = res[1];

        if (box_name == name) {
            sub_box = arr.slice(i, i+l)
        }
        i = i + l;
    }
    return sub_box;
}

function findFirstSampleFlag(arr) { // input Uint8Array
    // [moof [mfhd] [traf [tfhd] [tfdt] [trun]]]

    var traf = getSubBox(arr, "traf");
    if (traf==null) { return false; }

    var trun = getSubBox(traf, "trun");
    if (trun==null) { return false; }

    // ISO/IEC 14496-12:2012(E) .. pages 5 and 57
    // bytes: (size 4), (name 4), (version 1 + tr_flags 3)
    var flags = trun.slice(10,13); // console.log(flags);
    f = flags[1] & 4; // console.log(f);
    return f == 4;
}