我们如何使用 ffmpeg 将实时 rtmp 流转码为实时 hls 流?
Posted
技术标签:
【中文标题】我们如何使用 ffmpeg 将实时 rtmp 流转码为实时 hls 流?【英文标题】:How can we transcode live rtmp stream to live hls stream using ffmpeg? 【发布时间】:2013-11-08 14:35:09 【问题描述】:我正在尝试将实时 rtmp 流实时转换为 hls 流。
看完后我有了一些想法
http://sonnati.wordpress.com/2011/08/30/ffmpeg-%E2%80%93-the-swiss-army-knife-of-internet-streaming-%E2%80%93-part-iv/
我能够将实时 rtmp 流转换为 hls,但不能在运行时转换。当我运行命令并测试任何 hsl 文件(.m3u8 和 .ts)时,我看不到,但是当我中断命令并在那里检查时,我会根据需要获取 hls 文件。
我在谷歌上搜索了解决方案,但无法得到正确的答案。
任何人都可以帮助我吗?
在此先感谢...
【问题讨论】:
【参考方案1】:这是使用任何输入文件或流进行 HLS 流式传输的简短指南:
我遵循 user1390208 的方法,因此我只使用 FFMPEG 来生成我的服务器随后接收以提供 HLS 的 rtmp 流。我没有使用 Unreal/Wowza/Adobe,而是使用带有 rtmp 模块的免费服务器 nginx,它很容易设置。简而言之,这就是我的做法:Any input file or stream -> ffmpeg -> rtmp -> nginx server -> HLS -> Client
或更详细:
输入视频文件或流(http、rtmp 等) --> ffmpeg 实时转码为 x.264 + aac,输出到 rtmp --> nginx 获取 rtmp 并向用户(客户端)提供 HLS。 所以在客户端,你可以使用 VLC 或其他任何东西并连接到 nginx 提供的 .m3u8 文件。
我遵循了this nginx 设置指南。 This 是我的 nginx 配置文件。这就是我使用 ffmpeg 将输入文件转码为 rtmp 的方式:
ffmpeg -re -i mydirectory/myfile.mkv -c:v libx264 -b:v 5M -pix_fmt yuv420p -c:a:0 libfdk_aac -b:a:0 480k -f flv rtmp://localhost:12345/hls/mystream;
(.mkv 是 1080p 和 5.1 声音,根据您的输入,您应该使用较低的比特率!)
您从哪里获得 rtmp 流?
文件?然后你可以完全使用我的方法。任何带有流 Y 的服务器 X?那你得把ffmpeg命令改成:
ffmpeg -re -i rtmp://theServerX/yourStreamY -c:v libx264 -b:v 5M -pix_fmt yuv420p -c:a:0 libfdk_aac -b:a:0 480k -f flv rtmp://localhost:12345/hls/mystream;
或者如果您的 rtmp 流已经是 h.264/aac 编码,您可以尝试使用 ffmpeg 中的copy
选项将内容直接流式传输到 nginx。
正如你在我的 nginx 配置文件中看到的:
我的 rtmp 服务器有一个名为“hls”的“应用程序”。那是描述 nginx 在哪里监听 ffmpeg 的 rtmp 流的部分,这就是为什么 ffmpeg 流到rtmp://localhost:12345/hls/mystream;
我的 http 服务器有 location /hls
。这意味着在 VLC 中我可以连接到http://myServer:80/hls/mystream.m3u8
以访问 HLS 流。
一切都清楚了吗?直播愉快!
【讨论】:
这是一个非常有帮助的答案。 很好的答案!正是我需要的。 我可以在 nginx 中使用 RTSP/RTP 作为输入流吗?! 我不明白你如何将location /hls
连接到application hls
并从 /hls/mystream.m3u8 中获取流(至少它对我来说并不那么容易) .
@ROODAY 不,但您可以使用 hls_variant 标签使其工作,请参阅licson.net/post/setting-up-adaptive-streaming-with-nginx【参考方案2】:
作为对这个问题的更新,我已经设法在不使用 ffmpeg 的情况下完成了从 RTMP 到 HLS 的实时转码,如何?
只需使用与 user3069376 共享的完全相同的 nginx 配置文件,并非常小心生成 .m3uh 宣言的路径,RTMP 模块中的 hls 选项就可以解决这个问题。
至于视频播放器,Video.Js 就像一个魅力 o
【讨论】:
你能详细说明一下或分享一个conf文件吗? 据我所知,nginx在后台使用FFMPEG进行转码。【参考方案3】:试试这个 RTMP to HLS 命令行设置:
ffmpeg -v verbose -i rtmp://<host>:<port>/<stream> -c:v libx264 -c:a aac -ac 1 -strict -2 -crf 18 -profile:v baseline -maxrate 400k -bufsize 1835k -pix_fmt yuv420p -flags -global_header -hls_time 10 -hls_list_size 6 -hls_wrap 10 -start_number 1 <pathToFolderYouWantTo>/<streamName>.m3u8
HLS 提要中可能存在一些延迟。但是,它会起作用。
【讨论】:
非常简单的答案!有什么办法可以减少延迟?【参考方案4】:如果您已经准备好RTMP
直播并以 HLS 形式播放,那么您只需在直播名称后添加.m3u8
并将RTMP
链接到http
。例如,您有这样的RTMP
链接:
rtmp://XY.Y.ZX.Z/hls/chid
你必须像这样制作网址:
http://XY.Y.ZX.Z/hls/chid.m3u8
它会在 ios 中流畅播放。我已经尝试了以下代码,它工作正常。
func setPlayer()
// RTMP URL rtmp://XY.Y.ZX.Z/hls/chid be transcripted like this http://XY.Y.ZX.Z/hls/chid.m3u8 it will play normally.
let videoURL = URL(string: "http://XY.Y.ZX.Z/hls/chid.m3u8")
let playerItem = AVPlayerItem(url: videoURL!)
let adID = AVMetadataItem.identifier(forKey: "X-TITLE", keySpace: .hlsDateRange)
let metadataCollector = AVPlayerItemMetadataCollector(identifiers: [adID!.rawValue], classifyingLabels: nil)
//metadataCollector.setDelegate(self, queue: DispatchQueue.main)
playerItem.add(metadataCollector)
let player = AVPlayer(playerItem: playerItem)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.bounds
self.view.layer.addSublayer(playerLayer)
self.player = player
player.play()
但由于高分辨率视频流上传,它会很慢且滞后。如果在上传视频流时将分辨率调低,在低带宽网络下也能流畅运行。
请注意:它不是由 FFMPEG 运行的,因为我们已经运行了 RTMP FFMPEG,所以我喜欢这个。
【讨论】:
以上是关于我们如何使用 ffmpeg 将实时 rtmp 流转码为实时 hls 流?的主要内容,如果未能解决你的问题,请参考以下文章
windows下搭建ffmpeg+nginx+rtmp-module搭建实时视频环境
使用ffmpeg能否将rtsp的流转成rtmp流发出来?就如:ffmpeg -i rtsp://localhost/live -c copy -f flv rtm