zoukankan      html  css  js  c++  java
  • windows平台简易直播系统搭建

        最近做直播系统的朋友很多,正好前端时间也在做这一块,写片文章分享下开发心得,以为后用。

    直播系统我将它分为前堆推流,后台服务,客户端播放三大部分。前端推流基于ffmpeg,后台服务

    使用crtmp服务,播放端可以使用JWPlayer(网页端播放),也可以是CGplayer。

    一.前端推流

        推流可以采用命令: ffmpeg -i input  -vcodec copy -acodec copy -f flv rtmp://127.0.0.1/live/cgstream0

    input 可以是实时流,也可以是文件,如果是文件 需要加上-re。运用中需要将127.0.0.1换成rtmp所在机器的ip地址。

        用命令推流时间戳信息不能任意修改,想要达到一个满意的结果还是要用代码实现。rtmp推流前面有文章介绍过,

    这里将主要的几个方法介绍下,文章后面会给出完成的工程包。

          ffmpeg推流 如果不需要重写编码(视频源已经是编码好的数据),推流的过程比较简单就是一个demux和remux过程。

    主要方法代码如下:

      1.打开视频流,filename可以文件名称也可以是实时流url.

    int OpenInput(char *fileName)
    {
    	AVDictionary* options = nullptr; 
    	 context = avformat_alloc_context();
    	 cout << "Begin Open file Input " << endl;
    	 lastTime = av_gettime();
    	 context->interrupt_callback.callback = interrupt_cb;
    	int ret = avformat_open_input(&context, fileName, nullptr,&options);
    	if(ret < 0)
    	{
    		return  ret;
    	}
    	ret = avformat_find_stream_info(context,nullptr);
    	return ret;
    }
    

      2.创建输出上下文以及输出流,输出流的格式需要设置成flv

    int OpenOutput(char *fileName)
    {
        int ret = 0;
         ret  = avformat_alloc_output_context2(&outputContext, nullptr, "flv", fileName);
        if(ret < 0)
        {
            goto Error;
        }
        ret = avio_open2(&outputContext->pb, fileName, AVIO_FLAG_READ_WRITE,nullptr, nullptr);    
        if(ret < 0)
        {
            goto Error;
        }
        for(int i = 0; i < context->nb_streams; i++)
        {
            AVStream * stream = avformat_new_stream(outputContext, context->streams[i]->codec->codec);
           ret = avcodec_copy_context(stream->codec, context->streams[i]->codec);    if(ret < 0)
            {
                goto Error;
            }
    
        }
         ret = avformat_write_header(outputContext, nullptr);
        if(ret < 0)
        {
            goto Error;
        }
        return ret ;
    Error:
        if(outputContext)
        {
            for(int i = 0; i < outputContext->nb_streams; i++)
            {
                avcodec_close(outputContext->streams[i]->codec);
            }
            avformat_close_input(&outputContext);
        }
        return ret ;
    }
    
    

      3. 从输入流中读取音视频包

    shared_ptr<AVPacket>  ReadPacketFormSource()
    {
    	shared_ptr<AVPacket> packet(static_cast<AVPacket*>(av_malloc(sizeof(AVPacket))), 
    [&](AVPacket *p) { av_free_packet(p); av_freep(&p);}); av_init_packet(packet.get()); lastTime = av_gettime(); int ret = av_read_frame(context, packet.get()); if(ret >= 0) { return packet; } return nullptr; }

     4. 简单示例

     int main(int argc,char *argv[])	
    {   
     if(argc != 3) { std::cout <<" more or less parameters "<<endl; this_thread::sleep_for(chrono::seconds(1000)); return 0; } string fileInput= argv[1]; string fileOutput = argv[2]; thread task; bool streamEof = false; std::cout <<"input file is:"<< fileInput<< endl; std::cout <<"output file is:"<< fileOutput << endl; Init(); if(OpenInput((char *)fileInput.c_str()) < 0) { std::cout << "Open file Input failed!" << endl; this_thread::sleep_for(chrono::seconds(1000)); return 0; } std::cout <<"OpenInput successful"<<endl; if(OpenOutput((char *)fileOutput.c_str()) < 0) { std::cout << "Open file Output failed!" << endl; this_thread::sleep_for(chrono::seconds(1000)); return 0; } std::cout <<"OpenOutput successful"<<endl; int count = 0; auto timebase = av_q2d(context->streams[0]->time_base); int ret = 0; while(true) { auto packet = ReadPacketFormSource(); if(packet) { ret = av_write_frame(outputContext,packet.get()); } if(ret < 0 ) { break; } }
    }

      fileOutput 可以赋值为rtmp://127.0.0.1/live/cgstream0,表示视频流将要推送到本地的rtmp服务,默认端口是1935.

    二. 服务端

         服务端可以选择crtmpserver,crtmpserver开源,在windows平台以及linux平台下都可以运行,很多朋友总会问crtmpserver效率

    如何,有人质疑:crtmpserver是一个单线程的select模型,能否满足高并发的性能要求。质疑是有理的,有段时间我打算将crtmpserver改成

    并行结构,后来我还是放弃了,因为很多情况下用不到,还是等需求来了再改。大部分情况下,瓶颈并不在crtmpserver能并发多少路,而在网络

    带宽能支持多少路音视频流。随着人们对视频质量要求的提高,基本上视频的分辨率都是高清(1080p),码率基本会在4M以上。试想如果服务器

    网卡选择千兆网卡,单个网卡最多也就支持两百多路。一般来讲,服务器的cpu配置会比普通电脑高很多,支持几百路并发是不会出现性能问题。当然,

    如果追求最低的配置实现最高的并发也许crtmpserver不是最好的选择,但项目讲究实用,很多场合下足以满足需求。说到这里,肯定有人会问,如果并

    发访问的命令上千上万怎么办?答案是负载均衡。

        三. 播放端

             如果在网页上播放(IE),可以选择JwPlayer,如果用插件的也是可以。Android端播放器如果底层基于ffmpeg,也可以播放CrtmpServer

    转发的音视频流(ffmpeg需要引入librtmp库),IOS系统 同理。播放的url是rtmp://127.0.0.1/live/cgstream0。

        如果需要技术交流可加QQ 350197870,或加群流媒体/Ffmpeg/音视频 127903734讨论,CrtmpServer以及JwPlayer可以在群里

    直接下载,推流部分的源码过两天,也会上传上来。

        四. 如何搭建

      说了半天,有些新手朋友可能还不知道如何动手搭建一个简单的直播系统,怎么推流,又如何播放,下面我一步步介绍.

    1.首先 下载CrtmpServer服务(可以直接从群里下载),运行双击文件夹下的crtmpserver.exe,如果没有闪退,说明运行成功.

    2.下载ffmpeg.exe (可以从群里直接下载),在命令行执行 ffmpeg -i input  -vcodec copy -acodec copy -f flv rtmp://127.0.0.1/live/cgstream0

      127.0.0.1改成crtmpserver.exe所在服务器的地址.如果你在linux下推流,需要linux版本的ffmpeg。cgstream0可以根据需要任意修改。在  windows平台下如果推流成功ffmpeg会一直打印信息,出错也会有相应的提示。

    3.播放:播放可以用ffplayer.exe(可以从群里下载,这个工具对rtmp流支持不是很好 ,播放的地址是rtmp://127.0.0.1/live/cgstream0 live=1),JwPlayer(用法前面有文章介绍), 还可以用CGPlayer播放器

       (这是本人写的不检查时间戳的rtmp播放器 播放的地址是rtmp://127.0.0.1/live/cgstream0 live=1)。过两天会将下载地址粘贴上来。

    如需交流,可以加QQ群1038388075,766718184,或者QQ:350197870

     视频教程 播放地址: http://www.iqiyi.com/u/1426749687

    视频下载地址:http://www.chungen90.com/?news_3/

     Demo下载地址: http://www.chungen90.com/?news_2

  • 相关阅读:
    PHP03
    PHP02
    CentOS7安装GeoServer
    uDig配图与GeoServer添加Style
    udig下载、安装及汉化
    Intellij热部署插件JRebel
    IDEA中Lombok插件的安装与使用
    IEDA 自动生成类注释和方法注释
    Elasticsearch中text与keyword的区别
    Elastic search 7.X 去掉了type的原因
  • 原文地址:https://www.cnblogs.com/wanggang123/p/6340653.html
Copyright © 2011-2022 走看看