bilibili/YouTube 等网页如何实现实时广播?

现在的视频网页(如 bilibili, YouTube) 的视频直播是不是都是只用网页而不需要另外的程序呢(游戏直播未必?)?
如果是这样, 那要怎么实现?
我尝试用 mediaRecorder, 定时每3, 4秒上传一次到服务器, 但问题是 Chrome只支持录制成 WebM格式(暂时我只录制音频), 而苹果(iPhone和iMac的 Safari) 并不支持这个格式, 那我是不是必须要在用户上传服务器后转换成通用的格式, 如MP3?
(也搜索到利用本地WebWorker 来转换, 例如Facebook/WhatsApp 他们是这样做?


我现在尝试用户录制上传后服务器调用 FFmpeg转换成MP3格式再广播到正在收听的用户? 思路是否正确?

const constraints = { audio: true, video: false };
const mediaStream = await navigator.mediaDevices.getUserMedia(constraints)
mediaRecorder = new MediaRecorder(mediaStream);

我参考了下书上的(用node.js, 我直接用 shell 来调用ffmpeg了, 原理是否一样? node也是调用子进程?)

文件格式:

还有个问题就是把主播上传的音频分为一个个4秒的文件, 在"连接"的时候播放起来多少有一点点的卡(监听audio元素的 onended 事件, 立刻播放下一个, 当然提前下载)
那些实时视频是不是也是这样实现多少有个几秒延迟的?(例如某款手机的发布会视频…)

[这些问题也是Google了几天几夜, 算出的一点点方案, 放弃WebRTC因为要广播多个学生 ]

多个文件连播必然出现卡顿。

没做过直播系统,不过我猜应该不是拆分成多个文件上传/下载。媒体是流式的,有一帧播放一帧,不像 gif 必须下载完了才能播放。拆分成多个小文件徒增磁盘IO和网络传输开销。


ffmpeg 广播测试:

  • 先开启接收端
ffplay udp://127.0.0.1:12345
  • 开始广播
ffmpeg -i INPUT_VIDEO -v 0 -vcodec mpeg4 -f mpegts udp://127.0.0.1:12345

也可以直接把多个文件串起来广播:

ffmpeg -f concat -i playlist.txt -v 0 -vcodec mpeg4 -f mpegts udp://0.0.0.0:12345

但是会出现 keyframe 缺失的错误,估计需要在拆分的时候提前处理。

问题是在用Web上传的时候可以有一帧上传一帧吗(不断开)?
我尝试了下 可以不在断开的时候取值 但是是没有文件头的(除了第一个) 所以直接打开不能播放(合并在一起才可以), 所以我尝试三四秒重新打开一次(搜寻过怎么添加那个头文件没有结果), 或许可以实时上传广播给客户端?
但是Safari不支持Chrome的 WebM格式, 我要转换成MP3 格式

直播通常是用 m3u8 来播的

录制端传到服务器,服务器经过若干次cdn,最后下载到播放端。

必须CDN吗? 直接阿里的云服务器 带宽不够支撑(我买的动态流量付款, 带宽极限是10M/S) ?
要是几秒几秒上传一次的那种吧?

如果是你要广播给很多人的话,就需要