基于智慧教室|無紙化會議的新選擇:RTMP解決方案

基于智慧教室或是會議的技術方案,一般主要是涉及到屏幕采集和推送,整體技術方案這塊,一般建議走RTMP,說到這里,好人開發者提到,市面上也有RTSP的技術方案,甚至RTSP組播方案,這塊,大牛直播SDK Github 也做過相關對比,總的來說60人智慧教室或類似同屏場景下,最可靠的還是RTMP的解決方案(不贅述,具體可自行測試對比)。

有人說,RTMP延遲大,這種說法,相對片面,好多是由于推拉流模塊本身問題導致(如果服務器系NIGNX或SRS,基本可排除服務器轉發導致的大時延,不要再賴服務器了),從我們官方和實際場景來看,RTMP整體技術方案,延遲可做到1秒內,毫秒級。

組網這塊,無線組網,需要好的AP模塊才能撐得住大的并發流量,推送端到AP,最好是有線網鏈接。

服務器:如果Windows平臺,可以考慮NGINX,如果是Linux,可以考慮SRS或NGINX.

以下分平臺介紹相關配置選項:

Windows平臺RTMP推送端

對應DEMO:SmartPublisherDemo.exe

1. 如果采集屏幕,只要采集部分區域的話,可以點擊“選取屏幕區域”按鈕,選擇需要采集的區域,采集推送過程中,可以移動采集區域;

2. 如果是高分屏(如有些采集設備,是4K屏,原始分辨率過高),用戶又不想推這么高的分辨率的話,可以選中“縮放屏幕大小”,并指定縮放比例,可以先縮放,后編碼推送數據;

3. 設置采集幀率:如果是PPT/Word文檔類,一般8-12幀足矣,如果是電影之類,可以設置到20-30幀不等,關鍵幀間隔一般設置到幀率的2-4倍,屏幕推送的話,建議平均碼率模式;

4. 如果需要采集電腦端輸出的聲音,可以選中“采集揚聲器”,如果需要采集外部麥克風的音頻,選擇“采集麥克風”即可,并選擇對應的采集設備;

5. 設置下推送的RTMP URL,然后,點擊“推送”,就可以了;

6. 如果想預覽推送出去的數據,點擊“預覽”即可,想停止預覽的話,點擊“停止預覽”即可。

Android平臺RTMP屏幕推送端

對應工程:SmartServicePublisherV2

需要注意的事項:

1. Android 8.0及以上版本設備,需要加入省電優化白名單,6.0以上版本,需要動態獲取audio權限,具體代碼如下:

        //加入省電優化白名單,以免8.0及以上版本設備后臺運行超過一分鐘被自動停掉
        //if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
        if (Build.VERSION.SDK_INT >=26)
        {
            if(!isIgnoringBatteryOptimizations())
            {
                gotoSettingIgnoringBatteryOptimizations();
            }
        }

        //6.0及以上版本,動態獲取Audio權限
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
        {
            RequestAudioPermission();
        }


    //拉起請求加入省電白名單彈窗
    private void gotoSettingIgnoringBatteryOptimizations() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            try {
                Intent intent = new Intent();
                String packageName = getPackageName();
                intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
                intent.setData(Uri.parse("package:" + packageName));
                startActivityForResult(intent, REQUEST_IGNORE_BATTERY_CODE);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    //動態獲取Audio權限
    private void RequestAudioPermission()
    {
        if (PackageManager.PERMISSION_GRANTED ==  ContextCompat.checkSelfPermission(this.getApplicationContext(), android.Manifest.permission.RECORD_AUDIO))
        {
        }
        else {
            //提示用戶開戶權限音頻
            String[] perms = {"android.permission.RECORD_AUDIO"};
            ActivityCompat.requestPermissions(this, perms, RESULT_CODE_STARTAUDIO);
        }
    }

2. 持續的補幀策略,防止屏幕不動,沒數據下去;

3. 如果需要傳部分區域下去,可以用 SmartPublisherOnCaptureVideoClipedRGBAData() 接口;

4. 橫豎屏切換,上層無需過問,底層會自動切。

iOS平臺RTMP屏幕推送端

對應工程: SmartServiceCameraPublisherV2

注意事項:ReplayKit2 的直播擴展目前是有50M的內存使用限制,超過此限制系統會直接殺死擴展進程,因此 ReplayKit2 上建議推流分辨率和幀率、碼率不要太高。

以下是核心processSampleBuffer() 處理,iOS 11.0以上 加入了橫豎屏自動切換適配:

- (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer
                   withType:(RPSampleBufferType)sampleBufferType {
    
    CGFloat cur_memory = [self GetCurUsedMemoryInMB];
    
    if( cur_memory > 20.0f)
    {
        //NSLog(@"processSampleBuffer cur: %.2fM", cur_memory);
        return;
    }
        
    switch (sampleBufferType) {
        case RPSampleBufferTypeVideo:
            {
                if (!CMSampleBufferIsValid(sampleBuffer))
                    return;
                
                NSInteger rotation_degress = 0;
                //11.1以上支持自動旋轉
    #ifdef __IPHONE_11_1
                if (UIDevice.currentDevice.systemVersion.floatValue > 11.1) {
                    CGImagePropertyOrientation orientation = ((__bridge NSNumber*)CMGetAttachment(sampleBuffer, (__bridge CFStringRef)RPVideoSampleOrientationKey , NULL)).unsignedIntValue;
                    
                    //NSLog(@"cur org: %d", orientation);
                    
                    switch (orientation)
                    {
                        //豎屏
                        case kCGImagePropertyOrientationUp:{
                            rotation_degress = 0;
                        }
                            break;
                        case kCGImagePropertyOrientationDown:{
                            rotation_degress = 180;
                            break;
                        }
                        case kCGImagePropertyOrientationLeft: {
                            //靜音鍵那邊向上 所需轉90度
                            rotation_degress = 90;
                        }
                            break;
                        case kCGImagePropertyOrientationRight:{
                            //關機鍵那邊向上 所需轉270
                            rotation_degress = 270;
                        }
                            break;
                        default:
                            break;
                    }
                }
    #endif
                
                //NSLog(@"RPSampleBufferTypeVideo");
                if(_smart_publisher_sdk)
                {
                    //[_smart_publisher_sdk SmartPublisherPostVideoSampleBuffer:sampleBuffer];
                    [_smart_publisher_sdk SmartPublisherPostVideoSampleBufferV2:sampleBuffer rotateDegress:rotation_degress];
                }
                
                //NSLog(@"video ts:%.2f", CMTimeGetSeconds(CMSampleBufferGetPresentationTimeStamp(sampleBuffer)));
            }
            break;
        case RPSampleBufferTypeAudioApp:
            //NSLog(@"RPSampleBufferTypeAudioApp");
            if (CMSampleBufferDataIsReady(sampleBuffer) != NO)
            {
                if(_smart_publisher_sdk)
                {
                    NSInteger type = 2;
                    [_smart_publisher_sdk SmartPublisherPostAudioSampleBuffer:sampleBuffer inputType:type];
                }
            }
            //NSLog(@"App ts:%.2f", CMTimeGetSeconds(CMSampleBufferGetPresentationTimeStamp(sampleBuffer)));
            
            break;
        case RPSampleBufferTypeAudioMic:
            //NSLog(@"RPSampleBufferTypeAudioMic");
            if(_smart_publisher_sdk)
            {
                NSInteger type = 1;
                [_smart_publisher_sdk SmartPublisherPostAudioSampleBuffer:sampleBuffer inputType:type];
            }
            //NSLog(@"Mic ts:%.2f", CMTimeGetSeconds(CMSampleBufferGetPresentationTimeStamp(sampleBuffer)));
            
            break;
        default:
            break;
    }
}

大牛直播SDK多路RTSP-RTMP轉RTMP官方定制版

視沃科技(大牛直播SDK)多路RTMP/RTSP轉RTMP轉發軟件,系原有轉發SDK基礎上,官方推出的Windows平臺定制版。在秉承低延遲、靈活穩定、低資源占用的前提下,客戶無需關注開發細節,只需圖形化配置轉發等各類參數,實現產品快速上線目的。

如監控類攝像機、NVR等,通過廠商說明或Onvif工具,獲取拉流的RTSP地址,圖形化配置,完成拉流轉發等操作,輕松實現標準RTMP服務器(或CDN)對接。

視頻轉發支持H.264、H.265(需要RTMP服務器或CDN支持擴展H.265),音頻支持配置PCMA/PCMU轉AAC后轉發,并支持只轉發/錄制視頻或音頻,RTSP拉流端支持鑒權和TCP/UDP模式設置和TCP/UDP模式自動切換,整個拉流、轉發模塊都有非常完善的自動重連機制。

此外,可以通過點擊拉流地址或推流地址欄,實現推拉流地址,同步到左側預覽框,實現推拉流音視頻數據預覽。

運維方面,官方定制版轉發系統支持7*24小時不間斷運行,自帶守護進程,轉發程序被誤關等各種操作后,會自動啟動運行,此外,還支持開機自動啟動轉發或錄像。

官方測試版有1小時限制,拉流超過一小時會自動停止,如需長期運行或直接授權,請聯系我們。

image.png

功能說明
  1. 啟動程序

支持從守護進程(如需啟動轉發程序,可點擊SmartStreamRelayToolDaemon.exe,守護進程會自動拉起SmartStreamRelayTool.exe,如需關閉轉發程序,請先關閉SmartStreamRelayToolDaemon,轉發程序方可正常關閉):

image.png
  1. 添加轉發項配置信息
image.png

配置說明:

添加配置項:點擊頁面“添加”按鈕:

2 序號:無需關注,系統自動生成;

2 名稱:該路轉發配置項的描述信息;

2 拉流地址(必須填):需要轉發的RTSP或RTMP地址;

2 推流RTMP地址:需要轉推的RTMP地址;

2 推流播放地址:需要預覽的播放地址;

2 音視頻轉發選項:可選擇之轉發音頻或視頻,亦或同時轉發音視頻;

2 錄像參數配置:可選擇錄制音頻或視頻,亦或音視頻同時錄制,并可設定錄像文件前綴。

備注:雙擊列表配置項,可以查看或編輯配置信息;

刪除配置項:選中需要刪除的配置數據,點擊頁面“刪除”按鈕:

image.png

如何預覽推拉流數據?

點擊需要預覽的“拉流地址”或“推流地址”,URL會同步到左側預覽框,即可實現推拉流數據本地預覽。

如不需播放音頻,點擊“靜音”選項即可。

如何轉發數據?

  1. 選中需要轉發的配置數據項目(如需全部轉發,點擊全選選項即可);
  2. 點擊“拉流”按鈕,拉流生效后,頁面“流下載速度”會顯示當前下載速度;

image.png

  1. 如需停止拉流,選中配置項,點擊“停止拉流”即可;
  2. 拉流后,選中需要轉發的配置項,點擊“推流”按鈕;
image.png
  1. 如需停止推流,選中配置項,點擊“停止推流”即可;
  2. 如需對某一路錄像,在完成“錄像全局配置”的前提下,選中配置項,點擊“錄像”即可;
image.png
  1. 如需停止錄像,選中配置項,點擊“停止錄像”即可。

系統配置:

2 支持程序啟動后自動開啟轉發;

2 支持程序啟動后自動開啟錄像(考慮到Windows平臺磁盤讀寫性能,Windows平臺不做多路錄像承諾)

2 開機后自動啟動(可配置開機自動啟動配置名);

image.png

錄像全局配置:

2 支持設置錄像存儲目錄;

2 支持設定單個錄像文件大小;

2 支持設置文件是否增加日期、時間;

2 支持設置是否音頻自動轉AAC編碼后存儲。

image.png
[Windows平臺多路RTSP|RTMP轉RTMP推送官方定制版]
QQ交流群:

QQ群1(已滿):499687479
QQ群2:294891451

Windows平臺多路RTSP/RTMP流轉RTMP流深度定制版

大牛直播SDK提供的RTSP/RTMP轉RTMP流模塊,具備低延遲、足夠穩定靈活、有狀態反饋機制、資源占用低跨平臺,以SDK形式提供,給開發者提供更大的便利,已應用于諸多專業第三方公司。

其中:Windows平臺對外提供C++ C#接口,Android提供JNI接口封裝,iOS提供object c封裝。

Windows/Android/iOS RTMP/RTSP多路流媒體轉發SDK功能支持:

  1. 支持拉取rtmp流;
  2. 支持拉取rtsp流;
  3. Windows支持本地flv文件轉發(支持制定文件位置轉發,或轉發過程中seek);
  4. 支持本地預覽;
  5. 支持轉發過程中,實時靜音;
  6. 支持轉發過程中,切換rtmp/rtsp url,此外,windows平臺還支持切換本地flv文件;
  7. 支持錄像模塊擴展,可邊轉發邊錄制,每個文件錄制開始結束,均有狀態回饋;
  8. 支持內網RTSP網關模塊擴展,拉取的流數據,可以流入到內網RTSP網關模塊,對外微型RTSP媒體流服務(RTSP url),便于內網訪問;
  9. 音頻:AAC,并支持拉流后的音頻(PCMU/PCMA,Speex等)轉AAC后再轉發;
  10. 視頻:H.264、H.265,支持h265轉發(rtsp/rtmp h265轉rtmp h265推送)

對應Demo:

  • Windows測試程序:SmartStreamRelayDemo.exe;
  • Windows C++工程:WIN-RelaySDK-CPP-Demo;
  • Windows C#工程:WIN-RelaySDK-CSharp-Demo;
  • Android工程:SmartRelayDemoV2;
  • iOS工程:SmartiOSRelayDemoV2。

鑒于部分公司人員配備不齊或產品開發周期短,一方面想用好的SDK,另一方面,苦于短期內沒有好的人力配備完成上層業務邏輯開發,我們聯合第三方開發者實現了Windows轉發模塊深度定制版本:

先睹為快:

1. 啟動SmartStreamRelayDemo.exe

2. 輸入登陸用戶名、密碼,其中,用戶名 admin 密碼123456

3. 如需配置拉流和轉發RTSP RTMP url,請直接在relayconfig.ini配置

4. 頁面編輯配置:
4.1 讀取INI文件,獲取relayconfig.ini配置項;
4.2 保存INI文件,把上層編輯后的URL配置保存下來,配置后的,可直接保存,以便下次使用
4.3 增加工作任務:頁面添加新的轉發配置項
4.4 啟動工作任務:啟動所有轉發
4.5 停止工作任務:停止所有轉發
4.6 錄制:如需錄制流,直接點擊“功能選項”->“錄制”按鈕,默認錄制到“record”目錄
4.7 移除任務:如需刪除某一路流,直接點擊“功能選項”->“移除”按鈕
4.8 拉流預覽:預覽拉取的RTMP/RTSP流,預覽過程中,可實時靜音
4.9 推流預覽:轉發后的RTMP流,可實時預覽,亦可實時靜音

4. demo版,有一小時顯示,每超過一小時,自動停止運行

5. 提供底層SDK授權,上層系統OEM或上層源碼授權

更多資料或demo下載:

Github:?https://github.com/daniulive/SmarterStreaming

官網:http://www.nokunlock.com

QQ群:

如何對RTSP播放器做功能和性能評估

好多開發者在做產品競品分析的時候,不知道如何界定一個RTSP播放器,大牛直播SDK認為,一個RTSP播放器,不是說有幾個類似于Open/Close接口就夠了,好的RTSP播放器需要具備以下功能和性能屬性:

1. 低延遲:大多數RTSP的播放都面向直播場景,所以,如果延遲過大,比如監控行業,小偷都走了,客戶端才看到,或者別人已經按過門鈴幾秒,主人才看到圖像,嚴重影響體驗,所以,低延遲是衡量一個好的RTSP播放器非常重要的指標,目前大牛直播SDK的RTSP播放延遲控制在幾百毫秒,VLC在幾秒,這個延遲,是長時間的低延遲,比如運行1天、一周、一個月甚至更久;

2. 音視頻同步或跳轉:有些開發者為了追求低延遲體驗,甚至不做音視頻同步,拿到audio video直接播放,導致a/v不同步,還有就是時間戳亂跳;

3. 支持多實例:一個好的播放器,需要支持同時播放多路音視頻數據,比如4-8-9-16-32窗口;

4. 支持buffer time設置:在一些有網絡抖動的場景,播放器需要支持精準的buffer time設置,一般來說,以毫秒計;

5. H.265的播放和錄制:除了H.264,還需要支持H.265,目前市面上的RTSP H.265攝像頭越來越多,支持H.265的RTSP播放器迫在眉睫,此外,單純的播放H.265還不夠,還需要可以能把H.265的數據能錄制下來;

6. TCP/UDP模式切換:考慮到好多服務器僅支持TCP或UDP模式,一個好的RTSP播放器需要支持TCP/UDP模式自動切換;

7. 靜音支持:比如,多窗口播放RTSP流,如果每個audio都播放出來,體驗非常不好,所以實時靜音功能非常必要;

8. 視頻view旋轉:好多攝像頭由于安裝限制,導致圖像倒置,所以一個好的RTSP播放器應該支持如視頻view實時旋轉(0° 90° 180° 270°)、水平反轉、垂直反轉;

9. 支持解碼后audio/video數據輸出(可選):大牛直播SDK接觸到好多開發者,希望能在播放的同時,獲取到YUV或RGB數據,進行人臉匹配等算法分析,所以音視頻回調可選;

10. 快照:感興趣或重要的畫面,實時截取下來非常必要;

11. 網絡抖動處理(如斷網重連):基本功能,不再贅述;

12. 跨平臺:一個好的播放器,跨平臺(Windows/Android/iOS)很有必要,起碼為了后續擴展性考慮,開發的時候,有這方面的考慮,目前大牛直播SDK的RTSP播放器,完美支持以上平臺;

13. 長期運行穩定性:提到穩定性,好多開發者不以為然,實際上,一個好的產品,穩定是最基本的前提,不容忽視!
14. 可以錄像:播放的過程中,隨時錄制下來感興趣的視頻片斷,存檔或其他二次處理;

15. log信息記錄:整體流程機制實時反饋,不多打log,但是不能一些重要的log,如播放過程中出錯等;

16. download速度實時反饋:可以看到實時下載速度反饋,以此來監聽網絡狀態;

17. 異常狀態處理:如播放的過程中,斷網、網絡抖動、來電話、切后臺后返回等各種場景的處理。

說了這么多,有開發者會反問,大牛直播SDK到底支持了哪些?以下做個簡單功能概述,如不單獨說明,系Windows、Android、iOS全平臺支持:

  • ?[支持播放協議]高穩定、超低延遲、業內首屈一指的RTSP直播播放器SDK;
  • ?[多實例播放]支持多實例播放;
  • ?[事件回調]支持網絡狀態、buffer狀態等回調;
  • ?[視頻格式]支持H.265、H.264,此外,Windows/Android平臺還支持RTSP MJPEG播放;
  • ?[音頻格式]支持AAC/PCMA/PCMU;
  • ?[H.264/H.265軟解碼]支持H.264/H.265軟解;
  • ?[H.264硬解碼]Android/iOS支持H.264硬解;
  • ?[H.265硬解]Android/iOS支持H.265硬解;
  • ?[H.264/H.265硬解碼]Android支持設置Surface模式硬解和普通模式硬解碼;
  • ?[RTSP模式設置]支持RTSP TCP/UDP模式設置;
  • ?[RTSP TCP/UDP自動切換]支持RTSP TCP、UDP模式自動切換;
  • ?[RTSP超時設置]支持RTSP超時時間設置,單位:秒;
  • ?[RTSP 401認證處理]支持上報RTSP 401事件,如URL攜帶鑒權信息,會自動處理;
  • ?[緩沖時間設置]支持buffer time設置;
  • ?[首屏秒開]支持首屏秒開模式;
  • ?[復雜網絡處理]支持斷網重連等各種網絡環境自動適配;
  • ?[快速切換URL]支持播放過程中,快速切換其他URL,內容切換更快;
  • ?[音視頻多種render機制]Android平臺,視頻:surfaceview/OpenGL ES,音頻:AudioTrack/OpenSL ES;
  • ?[實時靜音]支持播放過程中,實時靜音/取消靜音;
  • ?[實時快照]支持播放過程中截取當前播放畫面;
  • ?[渲染角度]支持0°,90°,180°和270°四個視頻畫面渲染角度設置;
  • ?[渲染鏡像]支持水平反轉、垂直反轉模式設置;
  • ?[實時下載速度更新]支持當前下載速度實時回調(支持設置回調時間間隔);
  • ?[解碼前視頻數據回調]支持H.264/H.265數據回調;
  • ?[解碼后視頻數據回調]支持解碼后YUV/RGB數據回調;
  • ?[解碼前音頻數據回調]支持AAC/PCMA/PCMU/SPEEX數據回調;
  • ?[音視頻自適應]支持播放過程中,音視頻信息改變后自適應;
  • ?[擴展錄像功能]完美支持和錄像SDK組合使用(支持RTSP H.265流錄制,支持PCMA/PCMU轉AAC后錄制,支持設置只錄制音頻或視頻)。

相關資料:Github:?https://github.com/daniulive/SmarterStreaming

基于AES加密的RTSP/RTMP多路轉發設計方案

很多開發者最近咨詢我們,除了我們Windows推送端采集編碼的音視頻數據可以加密外,其他RTSP/RTMP流如果想更安全的轉推到RTMP服務器或相應CDN改怎么辦?

實際上,我們在做RTMP整體加密方案的時候已經考慮到這種情況,SmartStreamRelayDemo在拉取RTSP或RTMP流,轉推RTMP的時候,可以選擇加密視頻,加密音頻或音視頻都加密,廢話不多說,參看代碼:

bool nt_stream_relay_wrapper::StartPush(const std::string& url)
{
    if ( is_pushing_ )
        return false;

    if ( url.empty() )
        return false;

    if ( !OpenPushHandle() )
        return false;

    auto push_handle = GetPushHandle();
    ASSERT(push_handle != nullptr);

    ASSERT(push_api_ != NULL);
    if ( NT_ERC_OK != push_api_->SetURL(push_handle, url.c_str(), NULL) )
    {
        if ( !is_started_rtsp_stream_ )
        {
            push_api_->Close(push_handle);
            SetPushHandle(nullptr);
        }

        return false;
    }

    // 加密測試 +++

    push_api_->SetRtmpEncryptionOption(push_handle, url.c_str(), 1, 1);

    NT_BYTE test_key[16] = {'1', '2', '3'};

    push_api_->SetRtmpEncryptionKey(push_handle, url.c_str(), test_key, 16);

    // 加密測試 --

    if ( NT_ERC_OK != push_api_->StartPublisher(push_handle, NULL) )
    {
        if ( !is_started_rtsp_stream_ )
        {
            push_api_->Close(push_handle);
            SetPushHandle(nullptr);
        }

        return false;
    }


    // // test push rtsp ++

    // push_api_->SetPushRtspTransportProtocol(push_handle, 1);
    // // push_api_->SetPushRtspTransportProtocol(push_handle, 2);

    // push_api_->SetPushRtspURL(push_handle, "rtsp://player.daniulive.com:554/liverelay111.sdp");

    // push_api_->StartPushRtsp(push_handle, 0);

    // // test push rtsp--

    is_pushing_ = true;

    return true;
}

上圖:

relay

這個時候,輸入轉發設置的Key(支持aes 128, aes 192, aes 256加密,即將發布SM4加密),方可正常播放音視頻數據。

此種方案的優勢在于基于AES音視頻逐幀數據加密音視頻數據,第三方即便是破解了URL,也沒法播放,通過抓包工具抓取到數據,也沒法正常顯示。

相關資料:Github:?https://github.com/daniulive/SmarterStreaming

Flutter下實現低延遲的跨平臺RTSP/RTMP播放

為什么要用Flutter?

Flutter是谷歌的移動UI框架,可以快速在iOS和Android上構建高質量的原生用戶界面。 Flutter可以與現有的代碼一起工作。在全世界,Flutter正在被越來越多的開發者和組織使用,并且Flutter是完全免費、開源的。

Flutter有哪些與眾不同

image

1. Beautiful – Flutter 允許你控制屏幕上的每一寸像素,這讓「設計」不用再對「實現」妥協;

2. Fast – 一個應用不卡頓的標準是什么,你可能會說 16ms 抑或是 60fps,這對桌面端應用或者移動端應用來說已足夠,但當面對廣闊的 AR/VR 領域,60fps 仍然會成為使人腦產生眩暈的瓶頸,而 Flutter 的目標遠不止 60fps;借助 Dart 支持的 AOT 編譯以及 Skia 的繪制,Flutter 可以運行的很快;

3. Productive – 前端開發可能已經習慣的開發中 hot reload 模式,但這一特性在移動開發中還算是個新鮮事。Flutter 提供有狀態的 hot reload 開發模式,并允許一套 codebase 運行于多端;其他的,再比如開發采用 JIT 編譯與發布的 AOT 編譯,都使得開發者在開發應用時可以更加高效;

4. Open – Dart / Skia / Flutter (Framework),這些都是開源的,Flutter 與 Dart 團隊也對包括 Web 在內的多種技術持開放態度,只要是優秀的他們都愿意借鑒吸收。而在生態建設上,Flutter 回應 GitHub Issue 的速度更是讓人驚嘆,因為是真的快(closed 狀態的 issue 平均解決時間為 0.29天);

除了支持APICloud, Unity3d, React Native外,大牛直播SDK為什么要做Flutter下的RTSP/RTMP播放器

首先,Flutter則是依靠Flutter Engine虛擬機在iOS和Android上運行,開發人員可以通過Flutter框架和API在內部進行交互。Flutter Engine使用C/C++編寫,具有低延遲輸入和高幀速率的特點,不像Unity3d一樣,我們是回調YUV/RGB數據,在Unity3d里面繪制,Flutter直接調用native SDK,效率更高。

其次,客戶和開發者驅動,Flutter發展至今,目前還沒有個像樣的RTSP或RTMP播放器,一個播放器,不是說,有個界面,有個開始、停止按鈕就可以了,一個好用的直播播放器,對功能和性能屬性要求很高,特別是穩定性和低延遲這塊,不謙虛的說,可能是首款功能強大、真正好用的Flutter RTSP/RTMP直播播放SDK

以大牛直播SDK的播放器為例:

RTMP直播播放器功能介紹:

  • [支持播放協議]高穩定、超低延遲(一秒內,行業內幾無效果接近的播放端)、業內首屈一指的RTMP直播播放器SDK;
  • [多實例播放]支持多實例播放;
  • [事件回調]支持網絡狀態、buffer狀態等回調;
  • [視頻格式]支持RTMP擴展H.265,H.264;
  • [音頻格式]支持AAC/PCMA/PCMU/Speex;
  • [H.264/H.265軟解碼]支持H.264/H.265軟解;
  • [H.264硬解碼]Android/iOS支持H.264硬解;
  • [H.265硬解]Android/iOS支持H.265硬解;
  • [H.264/H.265硬解碼]Android支持設置Surface模式硬解和普通模式硬解碼;
  • [緩沖時間設置]支持buffer time設置;
  • [首屏秒開]支持首屏秒開模式;
  • [低延遲模式]支持類似于線上娃娃機等直播方案的超低延遲模式設置(公網200~400ms);
  • [復雜網絡處理]支持斷網重連等各種網絡環境自動適配;
  • [快速切換URL]支持播放過程中,快速切換其他URL,內容切換更快;
  • [音視頻多種render機制]Android平臺,視頻:surfaceview/OpenGL ES,音頻:AudioTrack/OpenSL ES;
  • [實時靜音]支持播放過程中,實時靜音/取消靜音;
  • [實時快照]支持播放過程中截取當前播放畫面;
  • [渲染角度]支持0°,90°,180°和270°四個視頻畫面渲染角度設置;
  • [渲染鏡像]支持水平反轉、垂直反轉模式設置;
  • [實時下載速度更新]支持當前下載速度實時回調(支持設置回調時間間隔);
  • [解碼前視頻數據回調]支持H.264/H.265數據回調;
  • [解碼后視頻數據回調]支持解碼后YUV/RGB數據回調;
  • [解碼前音頻數據回調]支持AAC/PCMA/PCMU/SPEEX數據回調;
  • [音視頻自適應]支持播放過程中,音視頻信息改變后自適應;
  • [擴展錄像功能]完美支持和錄像SDK組合使用(支持RTMP擴展H.265流錄制,支持PCMA/PCMU/Speex轉AAC后錄制,支持設置只錄制音頻或視頻)

RTSP直播播放器功能介紹:

  • [支持播放協議]高穩定、超低延遲、業內首屈一指的RTSP直播播放器SDK;
  • [多實例播放]支持多實例播放;
  • [事件回調]支持網絡狀態、buffer狀態等回調;
  • [視頻格式]支持H.265、H.264,此外,Windows/Android平臺還支持RTSP MJPEG播放;
  • [音頻格式]支持AAC/PCMA/PCMU;
  • [H.264/H.265軟解碼]支持H.264/H.265軟解;
  • [H.264硬解碼]Android/iOS支持H.264硬解;
  • [H.265硬解]Android/iOS支持H.265硬解;
  • [H.264/H.265硬解碼]Android支持設置Surface模式硬解和普通模式硬解碼;
  • [RTSP模式設置]支持RTSP TCP/UDP模式設置;
  • [RTSP TCP/UDP自動切換]支持RTSP TCP、UDP模式自動切換;
  • [RTSP超時設置]支持RTSP超時時間設置,單位:秒;
  • [RTSP 401認證處理]支持上報RTSP 401事件,如URL攜帶鑒權信息,會自動處理;
  • [緩沖時間設置]支持buffer time設置;
  • [首屏秒開]支持首屏秒開模式;
  • [復雜網絡處理]支持斷網重連等各種網絡環境自動適配;
  • [快速切換URL]支持播放過程中,快速切換其他URL,內容切換更快;
  • [音視頻多種render機制]Android平臺,視頻:surfaceview/OpenGL ES,音頻:AudioTrack/OpenSL ES;
  • [實時靜音]支持播放過程中,實時靜音/取消靜音;
  • [實時快照]支持播放過程中截取當前播放畫面;
  • [渲染角度]支持0°,90°,180°和270°四個視頻畫面渲染角度設置;
  • [渲染鏡像]支持水平反轉、垂直反轉模式設置;
  • [實時下載速度更新]支持當前下載速度實時回調(支持設置回調時間間隔);
  • [解碼前視頻數據回調]支持H.264/H.265數據回調;
  • [解碼后視頻數據回調]支持解碼后YUV/RGB數據回調;
  • [解碼前音頻數據回調]支持AAC/PCMA/PCMU/SPEEX數據回調;
  • [音視頻自適應]支持播放過程中,音視頻信息改變后自適應;
  • [擴展錄像功能]完美支持和錄像SDK組合使用(支持RTSP H.265流錄制,支持PCMA/PCMU轉AAC后錄制,支持設置只錄制音頻或視頻)

Android和iOS手機上RTSP/RTMP播放效果:

1. 視頻播放效果:

http://www.iqiyi.com/w_19s8dv6yht.html

2. 界面截圖:

image

上接口:

//
//  smartplayer.dart
//  smartplayer
//
//  GitHub: https://github.com/daniulive/SmarterStreaming
//  website: http://www.nokunlock.com
//
//  Created by daniulive on 2019/02/25.
//  Copyright ? 2014~2019 daniulive. All rights reserved.
//

import 'dart:async';
import 'dart:convert';

import 'package:flutter/services.dart';

class EVENTID {
  static const EVENT_DANIULIVE_COMMON_SDK = 0x00000000;
  static const EVENT_DANIULIVE_PLAYER_SDK = 0x01000000;
  static const EVENT_DANIULIVE_PUBLISHER_SDK = 0x02000000;

  static const EVENT_DANIULIVE_ERC_PLAYER_STARTED =
      EVENT_DANIULIVE_PLAYER_SDK | 0x1;
  static const EVENT_DANIULIVE_ERC_PLAYER_CONNECTING =
      EVENT_DANIULIVE_PLAYER_SDK | 0x2;
  static const EVENT_DANIULIVE_ERC_PLAYER_CONNECTION_FAILED =
      EVENT_DANIULIVE_PLAYER_SDK | 0x3;
  static const EVENT_DANIULIVE_ERC_PLAYER_CONNECTED =
      EVENT_DANIULIVE_PLAYER_SDK | 0x4;
  static const EVENT_DANIULIVE_ERC_PLAYER_DISCONNECTED =
      EVENT_DANIULIVE_PLAYER_SDK | 0x5;
  static const EVENT_DANIULIVE_ERC_PLAYER_STOP =
      EVENT_DANIULIVE_PLAYER_SDK | 0x6;
  static const EVENT_DANIULIVE_ERC_PLAYER_RESOLUTION_INFO =
      EVENT_DANIULIVE_PLAYER_SDK | 0x7;
  static const EVENT_DANIULIVE_ERC_PLAYER_NO_MEDIADATA_RECEIVED =
      EVENT_DANIULIVE_PLAYER_SDK | 0x8;
  static const EVENT_DANIULIVE_ERC_PLAYER_SWITCH_URL =
      EVENT_DANIULIVE_PLAYER_SDK | 0x9;
  static const EVENT_DANIULIVE_ERC_PLAYER_CAPTURE_IMAGE =
      EVENT_DANIULIVE_PLAYER_SDK | 0xA;

  static const EVENT_DANIULIVE_ERC_PLAYER_RECORDER_START_NEW_FILE =
      EVENT_DANIULIVE_PLAYER_SDK | 0x21; /*錄像寫入新文件*/
  static const EVENT_DANIULIVE_ERC_PLAYER_ONE_RECORDER_FILE_FINISHED =
      EVENT_DANIULIVE_PLAYER_SDK | 0x22; /*一個錄像文件完成*/

  static const EVENT_DANIULIVE_ERC_PLAYER_START_BUFFERING =
      EVENT_DANIULIVE_PLAYER_SDK | 0x81;
  static const EVENT_DANIULIVE_ERC_PLAYER_BUFFERING =
      EVENT_DANIULIVE_PLAYER_SDK | 0x82;
  static const EVENT_DANIULIVE_ERC_PLAYER_STOP_BUFFERING =
      EVENT_DANIULIVE_PLAYER_SDK | 0x83;

  static const EVENT_DANIULIVE_ERC_PLAYER_DOWNLOAD_SPEED =
      EVENT_DANIULIVE_PLAYER_SDK | 0x91;
}

typedef SmartEventCallback = void Function(int, String, String, String);

class SmartPlayerController {
  MethodChannel _channel;
  EventChannel _eventChannel;
  SmartEventCallback _eventCallback;

  void init(int id) {
    _channel = MethodChannel('smartplayer_plugin_$id');
    _eventChannel = EventChannel('smartplayer_event_$id');
    _eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError);
  }

  void setEventCallback(SmartEventCallback callback) {
    _eventCallback = callback;
  }

  void _onEvent(Object event) {
    if (event != null) {
      Map valueMap = json.decode(event);
      String param = valueMap['param'];
      onSmartEvent(param);
    }
  }

  void _onError(Object error) {
    // print('error:'+ error);
  }

  Future<dynamic> _smartPlayerCall(String funcName) async {
    var ret = await _channel.invokeMethod(funcName);
    return ret;
  }

  Future<dynamic> _smartPlayerCallInt(String funcName, int param) async {
    var ret = await _channel.invokeMethod(funcName, {
      'intParam': param,
    });
    return ret;
  }

  Future<dynamic> _smartPlayerCallIntInt(
      String funcName, int param1, int param2) async {
    var ret = await _channel.invokeMethod(funcName, {
      'intParam': param1,
      'intParam2': param2,
    });
    return ret;
  }

  Future<dynamic> _smartPlayerCallString(String funcName, String param) async {
    var ret = await _channel.invokeMethod(funcName, {
      'strParam': param,
    });
    return ret;
  }

  /// 設置解碼方式 false 軟解碼 true 硬解碼 默認為false
  /// </summary>
  /// <param name="isHwDecoder"></param>
  Future<dynamic> setVideoDecoderMode(int isHwDecoder) async {
    return _smartPlayerCallInt('setVideoDecoderMode', isHwDecoder);
  }

  /// <summary>
  /// 設置音頻輸出模式: if 0: 自動選擇; if with 1: audiotrack模式, 此接口僅限于Android平臺使用
  /// </summary>
  /// <param name="use_audiotrack"></param>
  Future<dynamic> setAudioOutputType(int useAudiotrack) async {
    return _smartPlayerCallInt('setAudioOutputType', useAudiotrack);
  }

  /// <summary>
  /// 設置播放端緩存大小, 默認200毫秒
  /// </summary>
  /// <param name="buffer"></param>
  Future<dynamic> setBuffer(int buffer) async {
    return _smartPlayerCallInt('setBuffer', buffer);
  }

  /// <summary>
  /// 接口可實時調用:設置是否實時靜音,1:靜音; 0: 取消靜音
  /// </summary>
  /// <param name="is_mute"></param>
  Future<dynamic> setMute(int isMute) async {
    return _smartPlayerCallInt('setMute', isMute);
  }

  /// <summary>
  /// 設置RTSP TCP模式, 1: TCP; 0: UDP
  /// </summary>
  /// <param name="is_using_tcp"></param>
  Future<dynamic> setRTSPTcpMode(int isUsingTcp) async {
    return _smartPlayerCallInt('setRTSPTcpMode', isUsingTcp);
  }

  /// <summary>
  /// 設置RTSP超時時間, timeout單位為秒,必須大于0
  /// </summary>
  /// <param name="timeout"></param>
  Future<dynamic> setRTSPTimeout(int timeout) async {
    return _smartPlayerCallInt('setRTSPTimeout', timeout);
  }

  /// <summary>
  /// 設置RTSP TCP/UDP自動切換
  /// 對于RTSP來說,有些可能支持rtp over udp方式,有些可能支持使用rtp over tcp方式.
  /// 為了方便使用,有些場景下可以開啟自動嘗試切換開關, 打開后如果udp無法播放,sdk會自動嘗試tcp, 如果tcp方式播放不了,sdk會自動嘗試udp.
  /// </summary>
  /// <param name="is_auto_switch_tcp_udp"></param>
  Future<dynamic> setRTSPAutoSwitchTcpUdp(int is_auto_switch_tcp_udp) async {
    return _smartPlayerCallInt('setRTSPAutoSwitchTcpUdp', is_auto_switch_tcp_udp);
  }

  /// <summary>
  /// 設置快速啟動該模式,
  /// </summary>
  /// <param name="is_fast_startup"></param>
  Future<dynamic> setFastStartup(int isFastStartup) async {
    return _smartPlayerCallInt('setFastStartup', isFastStartup);
  }

  /// <summary>
  /// 設置超低延遲模式 false不開啟 true開啟 默認false
  /// </summary>
  /// <param name="mode"></param>
  Future<dynamic> setPlayerLowLatencyMode(int mode) async {
    return _smartPlayerCallInt('setPlayerLowLatencyMode', mode);
  }

  /// <summary>
  /// 設置視頻垂直反轉
  /// </summary>
  /// <param name="is_flip"></param>
  Future<dynamic> setFlipVertical(int is_flip) async {
    return _smartPlayerCallInt('setFlipVertical', is_flip);
  }

  /// <summary>
  /// 設置視頻水平反轉
  /// </summary>
  /// <param name="is_flip"></param>
  Future<dynamic> setFlipHorizontal(int is_flip) async {
    return _smartPlayerCallInt('setFlipHorizontal', is_flip);
  }

  /// <summary>
  /// 設置順時針旋轉, 注意除了0度之外, 其他角度都會額外消耗性能
  /// degress: 當前支持 0度,90度, 180度, 270度 旋轉
  /// </summary>
  /// <param name="degress"></param>
  Future<dynamic> setRotation(int degress) async {
    return _smartPlayerCallInt('setRotation', degress);
  }

  /// <summary>
  /// 設置是否回調下載速度
  /// is_report: if 1: 上報下載速度, 0: 不上報.
  /// report_interval: 上報間隔,以秒為單位,>0.
  /// </summary>
  /// <param name="is_report"></param>
  /// <param name="report_interval"></param>
  Future<dynamic> setReportDownloadSpeed(
      int isReport, int reportInterval) async {
    return _smartPlayerCallIntInt(
        'setReportDownloadSpeed', isReport, reportInterval);
  }

  /// <summary>
  /// Set playback orientation(設置播放方向),此接口僅適用于Android平臺
  /// </summary>
  /// <param name="surOrg"></param>
  /// surOrg: current orientation,  PORTRAIT 1, LANDSCAPE with 2
  Future<dynamic> setOrientation(int surOrg) async {
    return _smartPlayerCallInt('setOrientation', surOrg);
  }

  /// <summary>
  /// 設置是否需要在播放或錄像過程中快照
  /// </summary>
  /// <param name="is_save_image"></param>
  Future<dynamic> setSaveImageFlag(int isSaveImage) async {
    return _smartPlayerCallInt('setSaveImageFlag', isSaveImage);
  }

  /// <summary>
  /// 播放或錄像過程中快照
  /// </summary>
  /// <param name="imageName"></param>
  Future<dynamic> saveCurImage(String imageName) async {
    return _smartPlayerCallString('saveCurImage', imageName);
  }

  /// <summary>
  /// 播放或錄像過程中,快速切換url
  /// </summary>
  /// <param name="uri"></param>
  Future<dynamic> switchPlaybackUrl(String uri) async {
    return _smartPlayerCallString('switchPlaybackUrl', uri);
  }

  /// <summary>
  /// 創建錄像存儲路徑
  /// </summary>
  /// <param name="path"></param>
  Future<dynamic> createFileDirectory(String path) async {
    return _smartPlayerCallString('createFileDirectory', path);
  }

  /// <summary>
  /// 設置錄像存儲路徑
  /// </summary>
  /// <param name="path"></param>
  Future<dynamic> setRecorderDirectory(String path) async {
    return _smartPlayerCallString('setRecorderDirectory', path);
  }

  /// <summary>
  /// 設置單個錄像文件大小
  /// </summary>
  /// <param name="size"></param>
  Future<dynamic> setRecorderFileMaxSize(int size) async {
    return _smartPlayerCallInt('setRecorderFileMaxSize', size);
  }

  /// <summary>
  /// 設置錄像時音頻轉AAC編碼的開關
  /// aac比較通用,sdk增加其他音頻編碼(比如speex, pcmu, pcma等)轉aac的功能.
  /// </summary>
  /// <param name="is_transcode"></param>
  /// is_transcode: 設置為1的話,如果音頻編碼不是aac,則轉成aac,如果是aac,則不做轉換. 設置為0的話,則不做任何轉換. 默認是0.
  Future<dynamic> setRecorderAudioTranscodeAAC(int is_transcode) async {
    return _smartPlayerCallInt('setRecorderAudioTranscodeAAC', is_transcode);
  }

  /// <summary>
  /// 設置播放路徑
  /// </summary>
  Future<dynamic> setUrl(String url) async {
    return _smartPlayerCallString('setUrl', url);
  }

  /// <summary>
  /// 開始播放
  /// </summary>
  Future<dynamic> startPlay() async {
    return _smartPlayerCall('startPlay');
  }

  /// <summary>
  /// 停止播放
  /// </summary>
  Future<dynamic> stopPlay() async {
    return _smartPlayerCall('stopPlay');
  }

  /// <summary>
  /// 開始錄像
  /// </summary>
  Future<dynamic> startRecorder() async {
    return _smartPlayerCall('startRecorder');
  }

  /// <summary>
  /// 停止錄像
  /// </summary>
  Future<dynamic> stopRecorder() async {
    return _smartPlayerCall('stopRecorder');
  }

  /// <summary>
  /// 關閉播放
  /// </summary>
  Future<dynamic> dispose() async {
    return await _channel.invokeMethod('dispose');
  }

  void onSmartEvent(String param) {
    if (!param.contains(",")) {
      print("[onNTSmartEvent] android傳遞參數錯誤");
      return;
    }

    List<String> strs = param.split(',');

    String code = strs[1];
    String param1 = strs[2];
    String param2 = strs[3];
    String param3 = strs[4];
    String param4 = strs[5];

    int evCode = int.parse(code);

    var p1, p2, p3;
    switch (evCode) {
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_STARTED:
        print("開始。。");
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_CONNECTING:
        print("連接中。。");
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_CONNECTION_FAILED:
        print("連接失敗。。");
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_CONNECTED:
        print("連接成功。。");
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_DISCONNECTED:
        print("連接斷開。。");
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_STOP:
        print("停止播放。。");
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_RESOLUTION_INFO:
        print("分辨率信息: width: " + param1 + ", height: " + param2);
        p1 = param1;
        p2 = param2;
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_NO_MEDIADATA_RECEIVED:
        print("收不到媒體數據,可能是url錯誤。。");
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_SWITCH_URL:
        print("切換播放URL。。");
        break;

      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_CAPTURE_IMAGE:
        print("快照: " + param1 + " 路徑:" + param3);

        if (int.parse(param1) == 0) {
           print("截取快照成功。.");
        } else {
           print("截取快照失敗。.");
        }
        p1 = param1;
        p2 = param3;
        break;

      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_RECORDER_START_NEW_FILE:
        print("[record]開始一個新的錄像文件 : " + param3);
        p3 = param3;
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_ONE_RECORDER_FILE_FINISHED:
        print("[record]已生成一個錄像文件 : " + param3);
        p3 = param3;
        break;

      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_START_BUFFERING:
        print("Start_Buffering");
        break;

      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_BUFFERING:
        print("Buffering: " + param1 + "%");
        p1 = param1;
        break;

      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_STOP_BUFFERING:
        print("Stop_Buffering");
        break;

      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_DOWNLOAD_SPEED:
         print("download_speed:" + (double.parse(param1) * 8 / 1000).toStringAsFixed(0) + "kbps" + ", " + (double.parse(param1) / 1024).toStringAsFixed(0) + "KB/s");
        p1 = param1;
        break;
    }
    if (_eventCallback != null) {
      _eventCallback(evCode, p1, p2, p3);
    }
  }
}

image.gif

調用實例:

//
//  main.dart
//  main
//
//  GitHub: https://github.com/daniulive/SmarterStreaming
//  website: http://www.nokunlock.com
//
//  Created by daniulive on 2019/02/25.
//  Copyright ? 2014~2019 daniulive. All rights reserved.
//

import 'dart:io';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:smartplayer_native_view/smartplayer.dart';
import 'package:smartplayer_native_view/smartplayer_plugin.dart';

void main() {
  ///
  /// 強制豎屏
  ///
  SystemChrome.setPreferredOrientations(
      [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);

  runApp(new MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {
  SmartPlayerController player;
  double aspectRatio = 4.0 / 3.0;

  //輸入需要播放的RTMP/RTSP url
  TextEditingController playback_url_controller_ = TextEditingController();

  //Event事件回調顯示
  TextEditingController event_controller_ = TextEditingController();

  bool is_playing_ = false;
  bool is_mute_ = false;

  var rotate_degrees_ = 0;

  Widget smartPlayerView() {
      return SmartPlayerWidget(
        onSmartPlayerCreated: onSmartPlayerCreated,
      );
    }

  @override
  void initState() {
     print("initState called..");
    super.initState();
  }

  @override
  void didChangeDependencies() {
    print('didChangeDependencies called..');
    super.didChangeDependencies();
  }

  @override
  void deactivate() {
    print('deactivate called..');
    super.deactivate();
  }

  @override
  void dispose() {
    print("dispose called..");
    player.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar(
            title: const Text('Flutter SmartPlayer Demo'),
          ),
          body: new SingleChildScrollView(
            child: new Column(
              children: <Widget>[
                new Container(
                  color: Colors.black,
                  child: AspectRatio(
                    child: smartPlayerView(),
                    aspectRatio: aspectRatio,
                  ),
                ),
                new TextField(
                  controller: playback_url_controller_,
                  keyboardType: TextInputType.text,
                  decoration: InputDecoration(
                    contentPadding: EdgeInsets.all(10.0),
                    icon: Icon(Icons.link),
                    labelText: '請輸入RTSP/RTMP url',
                  ),
                  autofocus: false,
                ),
                new Row(
                  children: [
                    new RaisedButton(
                        onPressed: this.onSmartPlayerStartPlay,
                        child: new Text("開始播放")),
                    new Container(width: 20),
                    new RaisedButton(
                        onPressed: this.onSmartPlayerStopPlay,
                        child: new Text("停止播放")),
                    new Container(width: 20),
                    new RaisedButton(
                        onPressed: this.onSmartPlayerMute,
                        child: new Text("實時靜音")),
                  ],
                ),
                new Row(
                  children: [
                    new RaisedButton(
                        onPressed: this.onSmartPlayerSwitchUrl,
                        child: new Text("實時切換URL")),
                    new Container(width: 20),
                    new RaisedButton(
                        onPressed: this.onSmartPlayerSetRotation,
                        child: new Text("實時旋轉View")),
                  ],
                ),
                new TextField(
                  controller: event_controller_,
                  keyboardType: TextInputType.text,
                  decoration: InputDecoration(
                    contentPadding: EdgeInsets.all(10.0),
                    icon: Icon(Icons.event_note),
                    labelText: 'Event狀態回調',
                  ),
                  autofocus: false,
                ),
              ],
            ),
          )),
    );
  }

  void _eventCallback(int code, String param1, String param2, String param3) {
    String event_str;

    switch (code) {
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_STARTED:
        event_str = "開始..";
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_CONNECTING:
        event_str = "連接中..";
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_CONNECTION_FAILED:
        event_str = "連接失敗..";
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_CONNECTED:
        event_str = "連接成功..";
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_DISCONNECTED:
        event_str = "連接斷開..";
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_STOP:
        event_str = "停止播放..";
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_RESOLUTION_INFO:
        event_str = "分辨率信息: width: " + param1 + ", height: " + param2;
        setState(() {
          aspectRatio = double.parse(param1) / double.parse(param2);
          print('change aspectRatio:$aspectRatio');
        });
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_NO_MEDIADATA_RECEIVED:
        event_str = "收不到媒體數據,可能是url錯誤..";
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_SWITCH_URL:
        event_str = "切換播放URL..";
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_CAPTURE_IMAGE:
        event_str = "快照: " + param1 + " 路徑: " + param3;

        if (int.parse(param1) == 0) {
          print("截取快照成功。.");
        } else {
          print("截取快照失敗。.");
        }
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_RECORDER_START_NEW_FILE:
        event_str = "[record] new file: " + param3;
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_ONE_RECORDER_FILE_FINISHED:
        event_str = "[record] record finished: " + param3;
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_START_BUFFERING:
        //event_str = "Start Buffering";
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_BUFFERING:
        event_str = "Buffering: " + param1 + "%";
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_STOP_BUFFERING:
        //event_str = "Stop Buffering";
        break;
      case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_DOWNLOAD_SPEED:
        event_str = "download_speed:" +
            (double.parse(param1) * 8 / 1000).toStringAsFixed(0) +
            "kbps" +
            ", " +
            (double.parse(param1) / 1024).toStringAsFixed(0) +
            "KB/s";
        break;
    }

    event_controller_.text = event_str;
  }

  void onSmartPlayerCreated(SmartPlayerController controller) async {
    player = controller;
    player.setEventCallback(_eventCallback);

    var ret = -1;

    //設置video decoder模式
    var is_video_hw_decoder = 0;
    if (defaultTargetPlatform == TargetPlatform.android)
    {
      ret = await player.setVideoDecoderMode(is_video_hw_decoder);
    }
    else if(defaultTargetPlatform == TargetPlatform.iOS)
    {
      is_video_hw_decoder = 1;
      ret = await player.setVideoDecoderMode(is_video_hw_decoder);
    }

    //設置緩沖時間
    var play_buffer = 100;
    ret = await player.setBuffer(play_buffer);

    //設置快速啟動
    var is_fast_startup = 1;
    ret = await player.setFastStartup(is_fast_startup);

    //是否開啟低延遲模式
    var is_low_latency_mode = 0;
    ret = await player.setPlayerLowLatencyMode(is_low_latency_mode);

    //set report download speed(默認5秒一次回調 用戶可自行調整report間隔)
    ret = await player.setReportDownloadSpeed(1, 2);

    //設置RTSP超時時間
        var rtsp_timeout = 10;
      ret = await player.setRTSPTimeout(rtsp_timeout);

    var is_auto_switch_tcp_udp = 1;
        ret = await player.setRTSPAutoSwitchTcpUdp(is_auto_switch_tcp_udp);

    // 設置RTSP TCP模式
        //ret = await player.setRTSPTcpMode(1);

    //第一次啟動 為方便測試 設置個初始url
    playback_url_controller_.text = "rtmp://live.hkstv.hk.lxdns.com/live/hks2";
  }

  Future<void> onSmartPlayerStartPlay() async {
    var ret = -1;

    if (playback_url_controller_.text.length < 8) {
      playback_url_controller_.text =
          "rtmp://live.hkstv.hk.lxdns.com/live/hks1"; //給個初始url
    }

    //實時靜音設置 
    ret = await player.setMute(is_mute_ ? 1 : 0);

    if (!is_playing_) {
      ret = await player.setUrl(playback_url_controller_.text);
      ret = await player.startPlay();

      if (ret == 0) {
        is_playing_ = true;
      }
    }
  }

  Future<void> onSmartPlayerStopPlay() async {
    if (is_playing_) {
      await player.stopPlay();
      playback_url_controller_.clear();
      is_playing_ = false;
      is_mute_ = false;
    }
  }

  Future<void> onSmartPlayerMute() async {
    if (is_playing_) {
      is_mute_ = !is_mute_;
      await player.setMute(is_mute_ ? 1 : 0);
    }
  }

  Future<void> onSmartPlayerSwitchUrl() async {
    if (is_playing_) {
      if (playback_url_controller_.text.length < 8) {
        playback_url_controller_.text =
            "rtmp://live.hkstv.hk.lxdns.com/live/hks1";
      }

      await player.switchPlaybackUrl(playback_url_controller_.text);
    }
  }

  Future<void> onSmartPlayerSetRotation() async {
    if (is_playing_) {
      rotate_degrees_ += 90;
      rotate_degrees_ = rotate_degrees_ % 360;

      if (0 == rotate_degrees_) {
        print("旋轉90度");
      } else if (90 == rotate_degrees_) {
        print("旋轉180度");
      } else if (180 == rotate_degrees_) {
        print("旋轉270度");
      } else if (270 == rotate_degrees_) {
        print("不旋轉");
      }

      await player.setRotation(rotate_degrees_);
    }
  }
}

image.gif

經測試,Flutter環境下,RTMP和RTSP播放,擁有Native SDK一樣優異的播放體驗。

相關資料:Github:?https://github.com/daniulive/SmarterStreaming

QQ群:

Windows/Android/iOS平臺實現RTMP推送和播放端AES或SM4加解密實例

1. AES算法和SM4算法掃盲

AES算法

密碼學中的高級加密標準(AdvancedEncryptionStandard,AES),又稱Rijndael加密算法,是美國聯邦政府采用的一種區塊加密標準。這個標準用來替代原先的DES,已經被多方分析且廣為全世界所使用。經過五年的甄選流程,高級加密標準由美國國家標準與技術研究院(NIST)于2001年11月26日發布于FIPSPUB197,并在2002年5月26日成為有效的標準。2006年,高級加密標準已然成為對稱密鑰加密中最流行的算法之一。AES有一個固定的128位的塊大小和128,192或256位大小的密鑰大小。

該算法為比利時密碼學家JoanDaemen和VincentRijmen所設計,結合兩位作者的名字,以Rijndael命名之。AES在軟件及硬件上都能快速地加解密,相對來說較易于操作,且只需要很少的存儲空間。作為一個新的加密標準,目前正被部署應用到更廣大的范圍。

SM4算法

SM4算法全稱為SM4分組密碼算法,是國家密碼管理局2012年3月發布的第23號公告中公布的密碼行業標準。SM4算法是一個分組對稱密鑰算法,明文、密鑰、密文都是16字節,加密和解密密鑰相同。加密算法與密鑰擴展算法都采用32輪非線性迭代結構。解密過程與加密過程的結構相似,只是輪密鑰的使用順序相反。

SM4算法的優點是軟件和硬件實現容易,運算速度快。

2. 接口說明及調用展示

大牛直播SDK發布的跨平臺(Windows/Android/iOS平臺)的基于AES/SM4音視頻逐幀數據加密整體解決方案,第三方即便是破解了URL,也沒法播放,通過抓包工具抓取到數據,也沒法正常顯示。

此方案的難點是需要了解音視頻編碼相關的細節,才能進行適當的擴展。優點是常用的rtmp server可以直接支持,通用性很強。只需要改推送端和播放端就好。

2.1 Windows平臺RTMP推送端

C++接口:

		/*
		設置rtmp推送加密選項
		url: 考慮到可能推送到多個服務器,可以根據推送url配置不同的加密選項, 請確保url和SetURL一致
		is_encrypt_video: 1:表示視頻加密, 0:表示視頻不加密, 默認不加密, 其他值返回錯誤
		is_encrypt_audio: 1:表示音頻加密, 0:表示音頻不加密, 默認不加密, 其他值返回錯誤
		成功返回 NT_ERC_OK
		*/
		NT_UINT32(NT_API *SetRtmpEncryptionOption)(NT_HANDLE handle, NT_PCSTR url, NT_INT32 is_encrypt_video, NT_INT32 is_encrypt_audio);


		/*
		設置rtmp加密算法
		url: 考慮到可能推送到多個服務器,可以根據推送url配置不同的加密選項, 請確保url和SetURL一致
		encryption_algorithm: 加密算法, 當前支持aes和國標sm4. 1為aes, 2為sm4, 默認為aes.
		*/
		NT_UINT32(NT_API *SetRtmpEncryptionAlgorithm)(NT_HANDLE handle, NT_PCSTR url, NT_INT32 encryption_algorithm);


		/*
		設置rtmp推送加密密鑰
		url: 考慮到可能推送到多個服務器,可以根據推送url配置不同的加密選項, 請確保url和SetURL一致
		key:加密密鑰
		key_size: 如果加密算法是aes, key_size必須是16, 24, 32 這三個值, 其他返回錯誤; 如果加密算法是sm4, key_size必須是16, 其他值返回錯誤.
		成功返回 NT_ERC_OK
		*/
		NT_UINT32(NT_API *SetRtmpEncryptionKey)(NT_HANDLE handle, NT_PCSTR url, const NT_BYTE* key, NT_UINT32 key_size);


		/*
		設置rtmp推送加密IV(初始化向量), 這個接口不調用的話, 將使用默認IV
		url: 考慮到可能推送到多個服務器,可以根據推送url配置不同的加密選項, 請確保url和SetURL一致
		iv: 初始化向量
		iv_size: 當前必須是16, 其他值返回錯誤
		成功返回 NT_ERC_OK
		*/
		NT_UINT32(NT_API *SetRtmpEncryptionIV)(NT_HANDLE handle, NT_PCSTR url, const NT_BYTE* iv, NT_UINT32 iv_size);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

C#接口:

        /*
         * 設置rtmp推送加密選項
         * url: 考慮到可能推送到多個服務器,可以根據推送url配置不同的加密選項, 請確保url和SetURL一致
         * is_encrypt_video: 1:表示視頻加密, 0:表示視頻不加密, 默認不加密, 其他值返回錯誤
         * is_encrypt_audio: 1:表示音頻加密, 0:表示音頻不加密, 默認不加密, 其他值返回錯誤
         * 
         * 成功返回 NT_ERC_OK
		 */
        [DllImport(@"SmartPublisherSDK.dll")]
		public static extern UInt32 NT_PB_SetRtmpEncryptionOption(IntPtr handle, [MarshalAs(UnmanagedType.LPStr)]String url, Int32 is_encrypt_video, Int32 is_encrypt_audio);


		/*
         * 設置rtmp加密算法
         * url: 考慮到可能推送到多個服務器,可以根據推送url配置不同的加密選項, 請確保url和SetURL一致
         * encryption_algorithm: 加密算法, 當前支持aes和國標sm4. 1為aes, 2為sm4, 默認為aes.
		 */
        [DllImport(@"SmartPublisherSDK.dll")]
        public static extern UInt32 NT_PB_SetRtmpEncryptionAlgorithm(IntPtr handle, [MarshalAs(UnmanagedType.LPStr)]String url, Int32 encryption_algorithm);


		/*
         * 設置rtmp推送加密密鑰
         * url: 考慮到可能推送到多個服務器,可以根據推送url配置不同的加密選項, 請確保url和SetURL一致
         * key:加密密鑰
         * key_size: 如果加密算法是aes, key_size必須是16, 24, 32 這三個值, 其他返回錯誤; 如果加密算法是sm4, key_size必須是16, 其他值返回錯誤.
         * 成功返回 NT_ERC_OK
		 */
        [DllImport(@"SmartPublisherSDK.dll")]
        public static extern UInt32 NT_PB_SetRtmpEncryptionKey(IntPtr handle, [MarshalAs(UnmanagedType.LPStr)]String url, byte[] key, UInt32 key_size);

		/*
         * 設置rtmp推送加密IV(初始化向量), 這個接口不調用的話, 將使用默認IV
         * url: 考慮到可能推送到多個服務器,可以根據推送url配置不同的加密選項, 請確保url和SetURL一致
         * iv: 初始化向量
         * iv_size: 當前必須是16, 其他值返回錯誤
         * 成功返回 NT_ERC_OK
		 */
        [DllImport(@"SmartPublisherSDK.dll")]
        public static extern UInt32 NT_PB_SetRtmpEncryptionIV(IntPtr handle, [MarshalAs(UnmanagedType.LPStr)]String url, byte[] iv, UInt32 iv_size);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

C#調用展示:

				//設置RTMP加密(AES/SM4)
                /*
                Int32 is_encrypt_video = 1;
                Int32 is_encrypt_audio = 1;
                NTSmartPublisherSDK.NT_PB_SetRtmpEncryptionOption(publisher_handle_, url, is_encrypt_video, is_encrypt_audio);

                Int32 encryption_algorithm = 1;
                NTSmartPublisherSDK.NT_PB_SetRtmpEncryptionAlgorithm(publisher_handle_, url, encryption_algorithm);

                String key_str = "1234567890123456";

                UInt32 key_size = 16;

                if (key_str.Length <= 16)
                {
                    key_size = 16;
                }
                else if (key_str.Length <= 24)
                {
                    key_size = 24;
                }
                else
                {
                    key_size = 32;
                }

                byte[] key = new byte[key_size];

                if (key_str.Length <= 32)
                {
                    key = System.Text.Encoding.Default.GetBytes(key_str);
                }
                else
                {
                    key = System.Text.Encoding.Default.GetBytes(key_str.Substring(0, 32));
                }
                
                NTSmartPublisherSDK.NT_PB_SetRtmpEncryptionKey(publisher_handle_, url, key, key_size);

                String iv_str = "1234567890123456";

                UInt32 iv_size = 16;

                byte[] iv = new byte[iv_size];

                if (iv_str.Length <= 16)
                {
                    iv = System.Text.Encoding.Default.GetBytes(iv_str);
                }
                else
                {
                    iv = System.Text.Encoding.Default.GetBytes(key_str.Substring(0, 16));
                }

                NTSmartPublisherSDK.NT_PB_SetRtmpEncryptionIV(publisher_handle_, url, iv, iv_size);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

2.2 Windows平臺RTMP播放端

C++接口:

		/*
		*
		* 設置解密key,目前只用來解密rtmp加密流
		* key: 解密密鑰
		* size: 密鑰長度
		* 成功返回NT_ERC_OK
		*/
		NT_UINT32(NT_API *SetKey)(NT_HANDLE handle, const NT_BYTE* key, NT_UINT32 size);


		/*
		*
		* 設置解密向量,目前只用來解密rtmp加密流
		* iv:  解密向量
		* size: 向量長度
		* 成功返回NT_ERC_OK
		*/
		NT_UINT32(NT_API *SetDecryptionIV)(NT_HANDLE handle, const NT_BYTE* iv, NT_UINT32 size);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

C#接口:

        /*
         * 設置解密key,目前只用來解密rtmp加密流
		 * key: 解密密鑰
		 * size: 密鑰長度
		 * 成功返回NT_ERC_OK
		 */
        [DllImport(@"SmartPlayerSDK.dll")]
        public static extern UInt32 NT_SP_SetKey(IntPtr handle, byte[] key, UInt32 size);

		/*
		 * 設置解密向量,目前只用來解密rtmp加密流
		 * iv:  解密向量
		 * size: 向量長度
		 * 成功返回NT_ERC_OK
		 */
        [DllImport(@"SmartPlayerSDK.dll")]
        public static extern UInt32 NT_SP_SetDecryptionIV(IntPtr handle, byte[] iv, UInt32 size);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

調用展示:

            String key_str = "1234567890123456";

            UInt32 key_size = 16;

            if (key_str.Length <= 16)
            {
                key_size = 16;
            }
            else if (key_str.Length <= 24)
            {
                key_size = 24;
            }
            else
            {
                key_size = 32;
            }

            byte[] key = new byte[key_size];

            if (key_str.Length <= 32)
            {
                key = System.Text.Encoding.Default.GetBytes(key_str);
            }
            else
            {
                key = System.Text.Encoding.Default.GetBytes(key_str.Substring(0, 32));
            }

            NTSmartPlayerSDK.NT_SP_SetKey(player_handle_, key, key_size);

            String iv_str = "1234567890123456789012345678901211";

            UInt32 iv_size = 16;

            byte[] iv = new byte[iv_size];

            if (iv_str.Length <= 16)
            {
                iv = System.Text.Encoding.Default.GetBytes(iv_str);
            }
            else
            {
                iv = System.Text.Encoding.Default.GetBytes(key_str.Substring(0, 16));
            }
            
            iv = System.Text.Encoding.Default.GetBytes(iv_str);

            NTSmartPlayerSDK.NT_SP_SetDecryptionIV(player_handle_, iv, iv_size);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

2.3?Android平臺RTMP推送端

	/**
	 * 設置rtmp推送加密選項
	 *
	 * @param url: 考慮到可能推送到多個服務器,可以根據推送url配置不同的加密選項, 請確保url和SetURL一致
	 * @param is_encrypt_video: 1:表示視頻加密, 0:表示視頻不加密, 默認不加密, 其他值返回錯誤
	 * @param is_encrypt_audio: 1:表示音頻加密, 0:表示音頻不加密, 默認不加密, 其他值返回錯誤
	 *
	 * @return {0} if successful
	 */
	public native int SetRtmpEncryptionOption(long handle,  String url, int is_encrypt_video, int is_encrypt_audio);

	/**
	 * 設置rtmp加密算法
	 *
	 * @param url: 考慮到可能推送到多個服務器,可以根據推送url配置不同的加密選項, 請確保url和SetURL一致
	 * @param encryption_algorithm: 加密算法, 當前支持aes和國標sm4. 1為aes, 2為sm4, 默認為aes.
	 *
	 * @return {0} if successful
	 */
	public native int SetRtmpEncryptionAlgorithm(long handle,  String url, int encryption_algorithm);

	/**
	 * 設置rtmp推送加密密鑰
	 *
	 * @param url: 考慮到可能推送到多個服務器,可以根據推送url配置不同的加密選項, 請確保url和SetURL一致
	 * @param key:加密密鑰
	 * @param key_size: 當前key_size必須是16, 24, 32 這三個值,其他返回錯誤
	 *
	 * @return {0} if successful
	 */
	public native int SetRtmpEncryptionKey(long handle, String url, byte[] key, int key_size);

	/**
	 * 設置rtmp推送加密IV(初始化向量), 這個接口不調用的話, 將使用默認IV
	 *
	 * @param url: 考慮到可能推送到多個服務器,可以根據推送url配置不同的加密選項, 請確保url和SetURL一致
	 * @param iv:初始化向量
	 * @param iv_size: 當前必須是16, 其他值返回錯誤
	 *
	 * @return {0} if successful
	 */
	public native int SetRtmpEncryptionIV(long handle, String url, byte[] iv, int iv_size);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

調用展示:

if(encrypt_key != null && !encrypt_key.isEmpty()) {
                Log.i(TAG, "encrypt_key:" + encrypt_key);

                int is_encrypt_video = 1;
                int is_encrypt_audio = 1;

                if (pushType == 1)
                {
                    is_encrypt_video = 0;
                }
                else if (pushType == 2)
                {
                    is_encrypt_audio = 0;
                }

                libPublisher.SetRtmpEncryptionOption(publisherHandle, publishURL, is_encrypt_video, is_encrypt_audio);

                //加密算法可自行設置
                int encryption_algorithm = 1;
                libPublisher.SetRtmpEncryptionAlgorithm(publisherHandle, publishURL, encryption_algorithm);

                int key_len = 16;

                if (encrypt_key.length() > 16 && encrypt_key.length() <= 24) {
                    key_len = 24;
                } else if (encrypt_key.length() > 24) {
                    key_len = 32;
                }

                byte[] key = new byte[key_len];

                for (int i = 0; i < key_len; i++) {
                    key[i] = 0;
                }

                try {
                    byte[] key_utf8 = encrypt_key.getBytes("UTF-8");

                    int copy_len = key_utf8.length < key_len ? key_utf8.length : key_len;

                    for (int i = 0; i < copy_len; ++i) {
                        key[i] = key_utf8[i];
                    }

                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }

                int ret = libPublisher.SetRtmpEncryptionKey(publisherHandle, publishURL, key, key.length);

                if(ret != 0)
                {
                    Log.e(TAG, "Call SmartPublisherSetRtmpEncryptionKey failed, errorID: " + ret);
                }
            }

            if(encrypt_iv != null && !encrypt_iv.isEmpty()) {
                int iv_len = 16;

                byte[] iv = new byte[iv_len];

                for (int i = 0; i < iv_len; i++) {
                    iv[i] = 0;
                }

                try {
                    byte[] iv_utf8 = encrypt_iv.getBytes("UTF-8");

                    int copy_len = iv_utf8.length < iv_len ? iv_utf8.length : iv_len;

                    for (int i = 0; i < copy_len; ++i) {
                        iv[i] = iv_utf8[i];
                    }

                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }

                int ret = libPublisher.SetRtmpEncryptionIV(publisherHandle, publishURL, iv, iv.length);

                if(ret != 0)
                {
                    Log.e(TAG, "Call SetRtmpEncryptionIV failed, errorID: " + ret);
                }
            }

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

2.4 Android平臺RTMP播放端

	/**
	 * 設置解密key,目前只用來解密rtmp加密流
	 *
	 * @param handle: return value from SmartPlayerOpen()
	 *
	 * @param key:解密密鑰
	 *
	 * @param size:密鑰長度
	 *
	 * @return {0} if successful
	 */
	public native int SmartPlayerSetKey(long handle, byte[] key, int size);

	/**
	 * 設置解密向量,目前只用來解密rtmp加密流
	 *
	 * @param handle: return value from SmartPlayerOpen()
	 *
	 * @param iv:解密向量
	 *
	 * @param size:向量長度
	 *
	 * @return {0} if successful
	 */
	public native int SmartPlayerSetDecryptionIV(long handle, byte[] iv, int size);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

調用展示:

        if (encrypt_key != null && !encrypt_key.isEmpty()) {
            Log.i(TAG, "encrypt_key:" + encrypt_key);

            int key_len = 16;

            if (encrypt_key.length() > 16 && encrypt_key.length() <= 24) {
                key_len = 24;
            } else if (encrypt_key.length() > 24) {
                key_len = 32;
            }

            byte[] key = new byte[key_len];

            for (int i = 0; i < key_len; i++) {
                key[i] = 0;
            }

            try {
                byte[] key_utf8 = encrypt_key.getBytes("UTF-8");

                int copy_key_len = key_utf8.length < key_len ? key_utf8.length : key_len;

                for (int i = 0; i < copy_key_len; ++i) {
                    key[i] = key_utf8[i];
                }

            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

            libPlayer.SmartPlayerSetKey(playerHandle, key, key.length);

            if (encrypt_iv != null && !encrypt_iv.isEmpty()) {
                Log.i(TAG, "encrypt_iv:" + encrypt_iv);

                int iv_len = 16;
                byte[] iv = new byte[iv_len];

                for (int i = 0; i < iv_len; i++) {
                    iv[i] = 0;
                }

                try {
                    byte[] iv_utf8 = encrypt_iv.getBytes("UTF-8");

                    int copy_iv_len = iv_utf8.length < key_len ? iv_utf8.length : key_len;

                    for (int i = 0; i < copy_iv_len; ++i) {
                        iv[i] = iv_utf8[i];
                    }

                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }

                libPlayer.SmartPlayerSetDecryptionIV(playerHandle, iv, iv.length);
            }
        }

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

2.5?iOS平臺RTMP推送端

/**
 * 設置rtmp推送加密選項
 *
 * @param url 考慮到可能推送到多個服務器,可以根據推送url配置不同的加密選項, 請確保url和SetURL一致
 * @param is_encrypt_video 1:表示視頻加密, 0:表示視頻不加密, 默認不加密, 其他值返回錯誤
 * @param is_encrypt_audio 1:表示音頻加密, 0:表示音頻不加密, 默認不加密, 其他值返回錯誤
 *
 * @return {0} if successful
 */
-(NSInteger)SetRtmpEncryptionOption:(NSString*)url is_encrypt_video:(NSInteger)is_encrypt_video is_encrypt_audio:(NSInteger)is_encrypt_audio;

/**
 * 設置rtmp加密算法
 *
 * @param url 考慮到可能推送到多個服務器,可以根據推送url配置不同的加密選項, 請確保url和SetURL一致
 * @param encryption_algorithm 加密算法, 當前支持aes和國標sm4. 1為aes, 2為sm4, 默認為aes.
 *
 * @return {0} if successful
 */
-(NSInteger)SetRtmpEncryptionAlgorithm:(NSString*)url encryption_algorithm:(NSInteger)encryption_algorithm;

/**
 * 設置rtmp推送加密密鑰
 *
 * @param url 考慮到可能推送到多個服務器,可以根據推送url配置不同的加密選項, 請確保url和SetURL一致
 * @param key 加密密鑰
 * @param key_size 當前key_size必須是16, 24, 32 這三個值,其他返回錯誤
 *
 * @return {0} if successful
 */
-(NSInteger)SetRtmpEncryptionKey:(NSString*)url key:(unsigned char*)key key_size:(NSInteger)key_size;

/**
 * 設置rtmp推送加密IV(初始化向量), 這個接口不調用的話, 將使用默認IV
 *
 * @param url 考慮到可能推送到多個服務器,可以根據推送url配置不同的加密選項, 請確保url和SetURL一致
 * @param iv 初始化向量
 * @param iv_size 當前必須是16, 其他值返回錯誤
 *
 * @return {0} if successful
 */
-(NSInteger)SetRtmpEncryptionIV:(NSString*)url iv:(unsigned char*)iv iv_size:(NSInteger)iv_size;

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

調用展示:

    NSInteger key_length = [encrypt_key_ length];
    
    if(key_length > 0)
    {
        NSInteger is_encrypt_video = 1;
        NSInteger is_encrypt_audio = 1;
        
        if(video_opt_ == 0)
        {
            is_encrypt_video = 0;
        }
        
        if(audio_opt_ == 0)
        {
            is_encrypt_audio = 0;
        }
        
        [_smart_publisher_sdk SetRtmpEncryptionOption:rtmp_push_url is_encrypt_video:is_encrypt_video is_encrypt_audio:is_encrypt_audio];
        
        //默認AES加密,如需SM4加密,參數設置2即可
        NSInteger encryption_algorithm = 1;
        [_smart_publisher_sdk SetRtmpEncryptionAlgorithm:rtmp_push_url encryption_algorithm:encryption_algorithm];
        
        int key_len = 16;
        
        if (key_length > 16 && key_length <= 24) {
            key_len = 24;
        } else if (key_length > 24) {
            key_len = 32;
        }
        
        unsigned char key[32];
        memset(key, 0, 32);
        
        NSData* key_data = [encrypt_key_ dataUsingEncoding:NSUTF8StringEncoding];
        
        NSInteger copy_key_len = key_length < key_len ? key_length : key_len;
        
        Byte *copy_key_data = (Byte *)[key_data bytes];
        
        for(int i=0;i<copy_key_len;i++)
        {
            key[i] = copy_key_data[i];
        }
            
        [_smart_publisher_sdk SetRtmpEncryptionKey:rtmp_push_url key:key key_size:key_len];
        
        NSInteger iv_length = [encrypt_iv_ length];
        
        if(iv_length > 0)
        {
            int iv_len = 16;
            
            unsigned char iv[16];
            memset(iv, 0, 16);
            
            NSData* iv_data = [encrypt_iv_ dataUsingEncoding:NSUTF8StringEncoding];
            
            NSInteger copy_iv_len = iv_length < iv_len ? iv_length : iv_len;
            
            Byte *copy_iv_data = (Byte *)[iv_data bytes];
            
            for(int i=0;i<copy_iv_len;i++)
            {
                iv[i] = copy_iv_data[i];
            }
            
            [_smart_publisher_sdk SetRtmpEncryptionIV:rtmp_push_url iv:iv iv_size:iv_len];
        }

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

2.6?iOS平臺RTMP播放端

/**
 * 設置解密key,目前只用來解密rtmp加密流
 *
 * @param key 解密密鑰
 *
 * @param key_size 密鑰長度
 *
 * @return {0} if successful
 */
- (NSInteger)SmartPlayerSetKey:(unsigned char*)key key_size:(NSInteger)key_size;

/**
 * 設置解密向量,目前只用來解密rtmp加密流
 *
 * @param iv 解密向量
 *
 * @param iv_size 向量長度
 *
 * @return {0} if successful
 */
- (NSInteger)SmartPlayerSetDecryptionIV:(unsigned char*)iv iv_size:(NSInteger)iv_size;

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

調用展示:

    NSInteger key_length = [encrypt_key_ length];
    
    if(key_length > 0)
    {
        int key_len = 16;
        
        if (key_length > 16 && key_length <= 24) {
            key_len = 24;
        } else if (key_length > 24) {
            key_len = 32;
        }
        
        unsigned char key[32];
        memset(key, 0, 32);
        
        NSData* key_data = [encrypt_key_ dataUsingEncoding:NSUTF8StringEncoding];
  
        NSInteger copy_key_len = key_length < key_len ? key_length : key_len;
        
        Byte *copy_key_data = (Byte *)[key_data bytes];
        
        for(int i=0;i<copy_key_len;i++)
        {
            key[i] = copy_key_data[i];
        }
        
        [_smart_player_sdk SmartPlayerSetKey:key key_size:key_len];
    }
    
    NSInteger iv_length = [encrypt_iv_ length];
    
    if(iv_length > 0)
    {
        int iv_len = 16;
        
        unsigned char iv[16];
        memset(iv, 0, 16);
        
        NSData* iv_data = [encrypt_iv_ dataUsingEncoding:NSUTF8StringEncoding];
        
        NSInteger copy_iv_len = iv_length < iv_len ? iv_length : iv_len;
        
        Byte *copy_iv_data = (Byte *)[iv_data bytes];
        
        for(int i=0;i<copy_iv_len;i++)
        {
            iv[i] = copy_iv_data[i];
        }
        
        [_smart_player_sdk SmartPlayerSetDecryptionIV:iv iv_size:iv_len];
    }

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

3.注意事項

1. RTMP推送端什么時候調用加密接口?

回答:SetUrl之后,開始推送之前;

2. RTMP播放端,什么時候設置Key和IV解密向量?

回答:可以實現自動檢測,如檢測到推送的RTMP流系AES或SM4加密,會回調上來NT_SP_E_EVENT_ID_NEED_KEY事件,彈出輸入Key和IV框,如輸入的Key和IV不正確,播放端會收到NT_SP_E_EVENT_ID_KEY_ERROR事件

 NT_SP_E_EVENT_ID_NEED_KEY               = NT_SP_E_EVENT_ID_BASE | 0xC,  /*需要輸入解密key才能播放*/
 NT_SP_E_EVENT_ID_KEY_ERROR              = NT_SP_E_EVENT_ID_BASE | 0xD,  /*解密key不正確*/

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

3. 設置加解密Key和IV,有什么注意事項?

回答:key_size: 如果加密算法是aes, key_size必須是16, 24, 32 這三個值, 其他返回錯誤; 如果加密算法是sm4, key_size必須是16, 其他值返回錯誤;iv_size: 當前必須是16, 其他值返回錯誤。

相關資料:Github:?https://github.com/daniulive/SmarterStreaming

5張圖看懂如何實現Windows RTMP實時導播功能

一直以來,好多開發者苦于如何實現RTMP導播數據源實時切換,以下是大牛直播SDK導播切換說明,支持只切換數據源模式,或音視頻混音合成輸出模式:

數據源:

1. rtmp/rtsp音視頻流;

2. 本地屏幕/攝像頭/音頻數據;

3.本地flv文件。

輸出:

1. 多路流合成一路流后,推送到RTMP服務器;

2. 多路合成后的流,支持本地錄像、快照。

使用說明:

無視頻合成/音頻混音模式:

1. 打開SmartStreamRelayDemo.exe,輸入一路RTMP或RTSP流,在拉流地址輸入需要轉推的RTMP的url,如“rtmp://player.daniulive.com:1935/hls/stream666”,先點擊“拉流”,再點擊“推流”按鈕,如需本地預覽,可以點擊“預覽”按鈕。

打開SmartPlayer.exe,輸入剛剛設置的RTMP url:rtmp://player.daniulive.com:1935/hls/stream666,點擊“播放”即可。

如下圖所示:

?2. 切換一路RTMP數據源,輸入新的RTMP地址,點擊“切換拉流地址”即可:

?

3. 切換一路RTSP數據源,輸入新的RTSP地址,點擊“切換拉流地址”即可:

?

視頻合成/音頻混音模式:

1. 合流界面:

?

2. 播放輸出界面:

?

細心的你會發現,三路流分辨率和協議封裝不同,不過依然可自動切換,從而實現播放端觀眾無感知的導播體驗。

技術優勢:

1. 以SDK形式輸出,企業或開發者可根據需求完成多樣化的產品需求;

2. 行業內接口更靈活,資源占用更低;

3. 超低延遲輸出,效率更高;

4. 支持合流后的圖像預覽;

5. 支持合流后的音頻混音;

6. 支持導播過程中,隨時切斷某一路音視頻或音頻;

7. 豈止是合流,還可以實時錄像、快照等,接口更豐富。

相關資料和測試程序下載:

Github:?https://github.com/daniulive/SmarterStreaming

官網:http://www.nokunlock.com

如何在IE瀏覽器播放RTSP或RTMP流(RTSP/RTMP OCX播放控件)

好多開發者一直苦惱于如何在IE瀏覽器環境下,構建低延遲的RTSP或RTMP播放,對于RTSP流來說,好多公司通常的做法是把RTSP轉RTMP,然后分發到RTMP服務器,然后服務器轉http-flv出來,瀏覽器直接播放http-flv流,亦或通過flash控件直接播放RTMP流,還有就是,轉hls流出來,缺點是hls流延遲更大。

以上方案未嘗不可,如果對播放體驗和延遲要求更高,最簡單的做法是直接在IE瀏覽器下加載activex控件。

大牛直播SDK在現有SDK的基礎上,擴展了ocx控件,用于IE瀏覽器下的低延遲RTMP或RTSP播放,不謙虛的說,也可能是行業內功能支持和延遲最好的RTMP和RTSP播放器(支持RTMP/RTSP H.265(hevc)播放)。

頁面展示

1. 功能齊全的單畫面RTMP流或RTSP流播放:

?

2. 同時播放4路RTMP流或RTSP流畫面:

?

本地播放和集成說明:

點我下載DEMO

本地播放

DEMO說明

  1. 1_player_ocx.html:單個窗口功能展示。
  2. 4_player_ocx.html:4窗口功能展示。
  3. SmartPlayer.exe:cs架構播放器。

運行網頁播放端之前,請確保以管理員權限注冊ocx控件:regplayerocx.bat右鍵–>“以管理員身份運行(A)”,同理,反注冊也是需要管理員身份。

?

注意:大牛直播RTSP/RTMP播放OCX控件只適用于微軟IE瀏覽器。

對應封裝接口

	ULONG NT_SetLogPath();
	ULONG NT_Open();
	ULONG NT_Close();
	ULONG NT_StartPlay();
	ULONG NT_StopPlay();
	ULONG NT_SetMute(LONG is_mute);
	ULONG NT_SetURL(LPCTSTR url);
	ULONG NT_SetBuffer(LONG buffer);
	ULONG NT_SetRTSPTcpMode(LONG isUsingTCP);
	ULONG NT_SetRtspTimeout(LONG timeout);
	ULONG NT_SetRtspAutoSwitchTcpUdp(LONG is_auto_switch_tcp_udp);
	ULONG NT_SetFastStartup(LONG isFastStartup);
	ULONG NT_SetLowLatencyMode(LONG mode);
	ULONG NT_SetFlipVertical(LONG is_flip);
	ULONG NT_SetFlipHorizontal(LONG is_flip);
	ULONG NT_SetRotation(LONG degress);
	ULONG NT_SwitchURL(LPCTSTR url);
	ULONG NT_SetCaptureImagePath(LPCTSTR path);
	ULONG NT_CaptureImage();
	ULONG NT_SetRecorderDirectory(LPCTSTR dir);
	ULONG NT_SetRecorderFileMaxSize(ULONG size);
	ULONG NT_NT_SP_RecorderFileNameRuler(ULONG type, LPCTSTR file_name_prefix, LONG append_date, LONG append_time);
	ULONG NT_SetRecorderAudioTranscodeAAC(LONG is_transcode);
	ULONG NT_SetRecorderVideo(LONG is_record_video);
	ULONG NT_SetRecorderAudio(LONG is_record_audio);
	ULONG NT_StartRecorder();
	ULONG NT_StopRecorder();
	ULONG NT_FullScreen();
	void OnSDKEventReceived(ULONG event_id, ULONG param1);
	void OnVideoSizeReceived(ULONG width, ULONG height);

設置LOG存放路徑:

ULONG CSmartPlayerActiveXCtrl::NT_SetLogPath(LPCTSTR log_path)

請于NT_Open() 之前調用,代碼示例:

var obj = document.getElementById("SmartPlayerActiveX");
				
//如需記錄log文件,請確保log路徑存在, 如多級目錄, 可按照"D:\\Daniulive\\log"類似格式設定, 記錄文件名: smart_sdk.log

obj.NT_SetLogPath("D:\\");

接口說明:

1.? ULONG NT_Open();

打開player實例;
2. ULONG NT_Close();

關閉player實例;
3. ULONG NT_StartPlay();

開始播放;
4. ULONG NT_StopPlay();

停止播放;
5. ULONG NT_SetMute(LONG is_mute);

設置實時靜音;
6. ULONG NT_SetURL(LPCTSTR url);

設置播放的RTMP或RTSP url;
7. ULONG NT_SetBuffer(LONG buffer);

設置buffer time,緩沖時間,單位:毫秒;
8. ULONG NT_SetRTSPTcpMode(LONG isUsingTCP);

設置RTSP TCP/UDP播放模式;
9. ULONG NT_SetRtspTimeout(LONG timeout);

設置RTSP超時時間;
10. ULONG NT_SetRtspAutoSwitchTcpUdp(LONG is_auto_switch_tcp_udp);

設置是否自動切換TCP/UDP模式;
11. ULONG NT_SetFastStartup(LONG isFastStartup);

設置是否快速啟動;
12. ULONG NT_SetLowLatencyMode(LONG mode);

設置是否低延遲模式播放;
13. ULONG NT_SetFlipVertical(LONG is_flip);

設置垂直反轉模式圖像;
14. ULONG NT_SetFlipHorizontal(LONG is_flip);

設置水平反轉圖像;
15. ULONG NT_SetRotation(LONG degress);

設置旋轉圖像,可設定角度:0度 90度 180度 270度;
16. ULONG NT_SwitchURL(LPCTSTR url);

設置快速切換RTSP/RTMP url;
17. ULONG NT_SetCaptureImagePath(LPCTSTR path);

設置快照保存位置;
18. ULONG NT_CaptureImage();

設置實時快照功能;
19. ULONG NT_SetRecorderDirectory(LPCTSTR dir);

設置錄像保存位置;
20. ULONG NT_SetRecorderFileMaxSize(ULONG size);

設置單個錄像文件最大size,單位:兆;
21. ULONG NT_NT_SP_RecorderFileNameRuler(ULONG type, LPCTSTR file_name_prefix, LONG append_date, LONG append_time);

設置錄像文件命名規則:是否需要前綴、是否添加日期、是否添加時間;
22. ULONG NT_SetRecorderAudioTranscodeAAC(LONG is_transcode);

設置錄像音頻文件是否轉AAC后錄制,支持PCMA/PCMU/SPEEX轉AAC后錄制文件;
23. ULONG NT_SetRecorderVideo(LONG is_record_video);

設置是否錄制視頻;
24. ULONG NT_SetRecorderAudio(LONG is_record_audio);

設置是否錄制音頻;
25. ULONG NT_StartRecorder();

開始錄像;
26. ULONG NT_StopRecorder();

停止錄像;
27. ULONG NT_FullScreen();

全屏顯示窗口。

事件Event:?

1. void OnSDKEventReceived(ULONG event_id, ULONG param1);

回調網絡狀態、buffering狀態、下載速度等;

事件類型:

<script>
	var NT_EVENT_ID_SMART_PLAYER_SDK = 0x01000000;
	var NT_SP_E_EVENT_ID_BASE = NT_EVENT_ID_SMART_PLAYER_SDK;
	var NT_SP_E_EVENT_ID_CONNECTING				= NT_SP_E_EVENT_ID_BASE | 0x2;	/*連接中*/
	var NT_SP_E_EVENT_ID_CONNECTION_FAILED		= NT_SP_E_EVENT_ID_BASE | 0x3;	/*連接失敗*/
	var NT_SP_E_EVENT_ID_CONNECTED				= NT_SP_E_EVENT_ID_BASE | 0x4;	/*已連接*/
	var NT_SP_E_EVENT_ID_DISCONNECTED			= NT_SP_E_EVENT_ID_BASE | 0x5;	/*斷開連接*/
	var NT_SP_E_EVENT_ID_NO_MEDIADATA_RECEIVED	= NT_SP_E_EVENT_ID_BASE | 0x8;	/*收不到RTMP數據*/
	var NT_SP_E_EVENT_ID_RTSP_STATUS_CODE       = NT_SP_E_EVENT_ID_BASE | 0xB;  /*rtsp status code上報, 目前只上報401, param1表示status code*/

	/* 接下來請從0x81開始*/
	var NT_SP_E_EVENT_ID_START_BUFFERING = NT_SP_E_EVENT_ID_BASE | 0x81; /*開始緩沖*/
	var NT_SP_E_EVENT_ID_BUFFERING		 = NT_SP_E_EVENT_ID_BASE | 0x82; /*緩沖中, param1 表示百分比進度*/
	var NT_SP_E_EVENT_ID_STOP_BUFFERING  = NT_SP_E_EVENT_ID_BASE | 0x83; /*停止緩沖*/

	var NT_SP_E_EVENT_ID_DOWNLOAD_SPEED  = NT_SP_E_EVENT_ID_BASE | 0x91; /*下載速度, param1表示下載速度,單位是(Byte/s)*/

	var NT_SP_E_EVENT_ID_PLAYBACK_REACH_EOS		= NT_SP_E_EVENT_ID_BASE | 0xa1; /*播放結束, 直播流沒有這個事件,點播流才有*/
	var NT_SP_E_EVENT_ID_RECORDER_REACH_EOS		= NT_SP_E_EVENT_ID_BASE | 0xa2; /*錄像結束, 直播流沒有這個事件, 點播流才有*/
	var NT_SP_E_EVENT_ID_PULLSTREAM_REACH_EOS   = NT_SP_E_EVENT_ID_BASE | 0xa3; /*拉流結束, 直播流沒有這個事件,點播流才有*/
	var NT_SP_E_EVENT_ID_DURATION = NT_SP_E_EVENT_ID_BASE | 0xa8; /*視頻時長,如果是直播,則不上報,如果是點播的話, 若能從視頻源獲取視頻時長的話,則上報, param1表示視頻時長,單位是毫秒(ms)*/
</script>

調用展示:

<script language='javascript' for="SmartPlayerActiveX"  event="OnSDKEventReceived(event_id, param1)">
		// Test 1 - statically load the script (This is the basis for the hack)
		// Works on IE8, IE9, IE10 and IE11
		
		var show_str = "";

		var connection_status = event_id;

		if (connection_status != 0)
		{
			show_str += "鏈接狀態: ";

			if (NT_SP_E_EVENT_ID_CONNECTING == connection_status)
			{
				show_str += "鏈接中";
			}
			else if (NT_SP_E_EVENT_ID_CONNECTION_FAILED == connection_status)
			{
				show_str += "鏈接失敗";
			}
			else if (NT_SP_E_EVENT_ID_CONNECTED == connection_status)
			{
				show_str += "鏈接成功";
			}
			else if (NT_SP_E_EVENT_ID_DISCONNECTED == connection_status)
			{
				show_str += "鏈接斷開";
			}
			else if (NT_SP_E_EVENT_ID_NO_MEDIADATA_RECEIVED == connection_status)
			{
				show_str += "收不到數據";
			}
		}

		var download_speed = -1;
		
		if (NT_SP_E_EVENT_ID_DOWNLOAD_SPEED == event_id)
		{
			download_speed = param1;
		}
		
		if (download_speed != -1)
		{
			show_str += "下載速度:" + (download_speed * 8 / 1000).toFixed(0) + "kbps " + (download_speed / 1024).toFixed(0) + "KB/s";
		}
		
		var buffer_status = 0;
		
		if (NT_SP_E_EVENT_ID_START_BUFFERING == event_id
		|| NT_SP_E_EVENT_ID_BUFFERING == event_id
		|| NT_SP_E_EVENT_ID_STOP_BUFFERING == event_id)
		{
			buffer_status = event_id;
		}

		if (buffer_status != 0)
		{
			show_str += "緩沖狀態: ";

			if (NT_SP_E_EVENT_ID_START_BUFFERING == buffer_status)
			{
				show_str += "開始緩沖";
			}
			else if (NT_SP_E_EVENT_ID_BUFFERING == buffer_status)
			{
				show_str += "緩沖中" + param1 + "%";
			}
			else if (NT_SP_E_EVENT_ID_STOP_BUFFERING == buffer_status)
			{
				show_str += "結束緩沖";
			}
		}
		
		var EventMsgText = document.getElementById("EventMsg");
					
		EventMsgText.innerHTML = show_str;
	</script>

2. void OnVideoSizeReceived(ULONG width, ULONG height);

回調視頻寬高信息。

調用展示:

<script language='javascript' for="SmartPlayerActiveX"  event="OnVideoSizeReceived(width, height)">
	// Test 1 - statically load the script (This is the basis for the hack)
	// Works on IE8, IE9, IE10 and IE11
	
	var VideoResolutionText = document.getElementById("VideoResolution");
				
	VideoResolutionText.innerHTML = width + "*" + height;
</script>

SDK接口調用實例:

播放和錄像調用示例:

var is_player_opened = false;
var is_playing = false;
var is_recording = false;

function OpenPlayer()
{			   
	if(is_player_opened)
	{
		return;
	}
	
	var obj = document.getElementById("SmartPlayerActiveX");
	
	//如需記錄log文件,請確保log路徑存在, 如多級目錄, 可按照"D:\\Daniulive\\log"類似格式設定, 記錄文件名: smart_sdk.log
	obj.NT_SetLogPath("D:\\");
	
	var ret = obj.NT_Open();
	
	if(ret == 0)
	{   
		//設置TCP/UDP模式
		var rtsp_tcp_mode = document.getElementById("rtspTcpMode").checked ? 1 : 0;
		obj.NT_SetRTSPTcpMode(rtsp_tcp_mode);
		
		//設置RTSP超時時間
		var rtsp_timeout = document.getElementById("rtspTimeout").value;
		obj.NT_SetRtspTimeout(rtsp_timeout);
		
		//設置是否自動切換TCP-UDP模式
		var rtsp_auto_switch_tcp_udp = document.getElementById("rtspAutoSwitchTcpUdp").checked ? 1 : 0;
		obj.NT_SetRtspAutoSwitchTcpUdp(rtsp_auto_switch_tcp_udp);
		
		//設置是否快速啟動
		var fast_startup_mode = document.getElementById("fastStartupMode").checked ? 1 : 0;
		obj.NT_SetFastStartup(fast_startup_mode);
		
		//設置需要播放或錄像的RTSP/RTMP url
		var url = document.getElementById("playorReocordUrl").value;
		obj.NT_SetURL(url);
		
		//設置實時截圖路徑(可自行設置或選取系統存在的文件夾), 如多級目錄可按照"D:\\Daniulive\\image"類似格式設定
		//var image_path = "D:\\";
		obj.NT_SetCaptureImagePath(image_path);
	
		is_player_opened = true;
	}
}

function ClosePlayer()
{
	if(is_player_opened)
	{
		var obj = document.getElementById("SmartPlayerActiveX");
		obj.NT_Close();
		
		var EventMsgText = document.getElementById("EventMsg");	
		EventMsgText.innerHTML = "";
		
		is_player_opened = false;
	}
}

function OnBnClickedPlay()
{
	if(!isIE())
	{
		alert("非IE瀏覽器,請用IE打開播放控件..");
		return;
	}
	
	if(!isActiveXInstalled())
	{
		alert("控件未加載,請先加載控件..");
		return;
	}
	
	if(is_playing)
	{
		StopPlayback();
	}
	else
	{
		StartPlayback();
	}
}

//開始播放
function StartPlayback() {
	
	if(!is_playing && !is_recording)
	{
		OpenPlayer();
	}
	
	var obj = document.getElementById("SmartPlayerActiveX");

	//設置是否啟用低延遲模式
	var low_latency_mode = document.getElementById("lowlatencyMode").checked ? 1 : 0;
	obj.NT_SetLowLatencyMode(low_latency_mode);
					
	//設置緩沖時間
	var buffer_time = document.getElementById("bufferTime").value;
	obj.NT_SetBuffer(buffer_time);
					
	var ret = obj.NT_StartPlay();
	
	if(ret == 0)
	{
		is_playing = true;	
		
		var playBtnText = document.getElementById("playBtn");
	
		playBtnText.innerHTML = "停止播放";
	}		
}

//停止播放
function StopPlayback() {

	if(!is_playing)
	{
		return;
	}
	
	var obj = document.getElementById("SmartPlayerActiveX");

	obj.NT_StopPlay();
	 
	is_playing = false;
	
	var playBtnText = document.getElementById("playBtn");
	
	playBtnText.innerHTML = "開始播放";
	
	if(!is_recording)
	{
		ClosePlayer();
	}
	
	var VideoResolutionText = document.getElementById("VideoResolution");
			
	VideoResolutionText.innerHTML = "";
}
			
function OnBnClickedRecord()
{
	if(!isIE())
	{
		alert("非IE瀏覽器,請用IE打開播放控件..");
		return;
	}
	
	if(!isActiveXInstalled())
	{
		alert("控件未加載,請先加載控件..");
		return;
	}

	if(is_recording)
	{
		StopRecorder();
	}
	else
	{
		StartRecorder();
	}
}

//開始錄像
function StartRecorder() {
	
	if(!is_playing && !is_recording)
	{
		OpenPlayer();
	}
	
	var obj = document.getElementById("SmartPlayerActiveX");

	//設置實時錄像存放路徑(可自行設置或選取系統存在的文件夾), 如多級目錄可按照"D:\\Daniulive\\rec"類似格式設定
	var rec_dir = "D:\\";
	obj.NT_SetRecorderDirectory(rec_dir);
	
	var rec_max_size = 200;
	obj.NT_SetRecorderFileMaxSize(rec_max_size);
	
	var type = 0;
	var file_name_prefix = "daniulive";
	var append_date = 1;
	var append_time = 1;
	obj.NT_NT_SP_RecorderFileNameRuler(type, file_name_prefix, append_date, append_time);
	
	var is_transcode = 1;
	obj.NT_SetRecorderAudioTranscodeAAC(is_transcode);
	
	var is_record_video = 1;
	obj.NT_SetRecorderVideo(is_record_video);
	
	var is_record_audio = 1;
	obj.NT_SetRecorderAudio(is_record_audio);
	
	var ret = obj.NT_StartRecorder();
	
	if(ret == 0)
	{
		is_recording = true;
		
		var recordBtnText = document.getElementById("recordBtn");
	
		recordBtnText.innerHTML = "停止錄像";
	}
}

//停止錄像
function StopRecorder() {

	if(!is_recording)
	{
		return;
	}
	
	var obj = document.getElementById("SmartPlayerActiveX");

	obj.NT_StopRecorder();
	
	is_recording = false;
	
	var recordBtnText = document.getElementById("recordBtn");
	
	recordBtnText.innerHTML = "開始錄像";
	
	if(!is_playing)
	{
		ClosePlayer();
	}
}

快速切換URL調用示例:

//快速切換播放URL
function SwitchUrl() {

	if(!is_playing)
	{
		return;
	}

	var obj = document.getElementById("SmartPlayerActiveX");

	var switch_url = document.getElementById("playorReocordUrl").value;
	obj.NT_SwitchURL(switch_url);
}

實時靜音調用示例:

//實時靜音
var is_mute = 1;	
function SetMute() {
	
	var obj = document.getElementById("SmartPlayerActiveX");
	
	obj.NT_SetMute(is_mute);
	
	var muteText = document.getElementById("MuteBtn");
	
	if(is_mute == 1 )
	{
		is_mute = 0;
		muteText.innerHTML = "取消靜音";
	}
	else
	{
		is_mute = 1;
		muteText.innerHTML  = "實時靜音";
	}
}

視頻view垂直反轉、水平反轉、旋轉調用示例:

//垂直反轉
var is_flip_vertical = 1;
function SetFlipVertical() {
	
	var obj = document.getElementById("SmartPlayerActiveX");
	
	obj.NT_SetFlipVertical(is_flip_vertical);
	
	var flipVerticalText = document.getElementById("FlipVerticalBtn");
	
	if(is_flip_vertical == 1 )
	{
		is_flip_vertical = 0;
		flipVerticalText.innerHTML = "取消反轉";
	}
	else
	{
		is_flip_vertical = 1;
		flipVerticalText.innerHTML  = "垂直反轉";
	}
}

//水平反轉
var is_flip_horizontal = 1;
function SetFlipHorizontal() {
	
	var obj = document.getElementById("SmartPlayerActiveX");
	
	obj.NT_SetFlipHorizontal(is_flip_horizontal);
	
	var flipHorizontalText = document.getElementById("FlipHorizontalBtn");
	
	if(is_flip_horizontal == 1 )
	{
		is_flip_horizontal = 0;
		flipHorizontalText.innerHTML = "取消反轉";
	}
	else
	{
		is_flip_horizontal = 1;
		flipHorizontalText.innerHTML  = "水平反轉";
	}
}

//視頻view旋轉
var rotate_degrees_ = 0;
function SetRotation() {
	
	rotate_degrees_ += 90;
	rotate_degrees_ = rotate_degrees_ % 360;
	
	var obj = document.getElementById("SmartPlayerActiveX");
	
	obj.NT_SetRotation(rotate_degrees_);
	
	var rotateText = document.getElementById("RotateBtn");
					
	if (0 == rotate_degrees_)
	{
		rotateText.innerHTML = "旋轉90度";
	}
	else if (90 == rotate_degrees_)
	{
		rotateText.innerHTML = "旋轉180度";
	}
	else if (180 == rotate_degrees_)
	{
		rotateText.innerHTML = "旋轉270度";
	}
	else if (270 == rotate_degrees_)
	{
		rotateText.innerHTML = "不旋轉";
	}
}

實時截圖調用示例:

function CaptureImage() {
	var obj = document.getElementById("SmartPlayerActiveX");

	obj.NT_CaptureImage();
}

全屏顯示窗口調用示例:

//全屏顯示窗口
function FullScreen() {
	var obj = document.getElementById("SmartPlayerActiveX");

	obj.NT_FullScreen();
}

相關資料和測試控件下載:

Github:?https://github.com/daniulive/SmarterStreaming

官網:http://www.nokunlock.com

QQ群:

RTSP直播推流SDK

大牛直播RTSP推送端SDK特點:

  1. 全自研框架,易于擴展,自適應算法讓延遲更低、采集編碼傳輸效率更高;
  2. 所有功能以SDK接口形式提供,所有狀態,均有event回調,完美支持斷網自動重連;
  3. SDK模塊化,可和大牛直播播放器SDK組合實現流媒體數據轉發、內置輕量級RTSP服務、連麥、一對一互動等場景;
  4. Windows推送端SDK以層級模式提供,開發者可以自行組合數據源(如多攝像頭/屏幕/水印疊加);
  5. 支持外部YUV/RGB/H.264/AAC/SPEEX/PCMA/PCMU數據源接入;
  6. 所有參數均可通過SDK接口單獨設置,亦可通過默認參數,傻瓜式設置;
  7. RTMP推送、RTSP推送、錄像、內置輕量級RTSP服務模塊完全分離,可單獨使用亦可組合使用;
  8. 業內甚至很難找到效果接近的SDK

功能支持:

如不單獨說明,系Windows、Android、iOS全平臺支持。

  • ?[視頻采集處理]Windows平臺涵蓋“Windows視頻采集處理SDK”功能;
  • ?[音頻采集處理]Windows平臺涵蓋“Windows音頻采集處理SDK”功能;
  • ?[本地預覽]Windows平臺支持攝像頭/屏幕/合成數據實時預覽功能,Android/iOS平臺支持本地前后置攝像頭預覽;
  • ?[攝像頭反轉/旋轉]Windows平臺支持攝像頭水平反轉、垂直反轉、0°/90°/180°/270°旋轉;
  • ?[攝像頭采集]除常規YUV格式外,還支持MJPEG格式的攝像頭采集;
  • ?[RTSP推流]超低延時的RTSP協議直播推流SDK;
  • ?[視頻格式]Windows/Android平臺支持H.264/H.265編碼(Android H.265硬編碼),iOS平臺支持H.264編碼;
  • ?[音頻格式]Windows/Android/iOS平臺支持AAC編碼;
  • ?[H.264硬編碼]Android/iOS平臺支持H.264硬編碼;
  • ?[H.265硬編碼]Android/iOS平臺支持H.265硬編碼;
  • ?[硬編碼自適應]Android/iOS平臺支持硬編碼自適應,如檢測到硬編碼不支持,自動切換到軟編(iOS如H.265硬編,先切換到H.264硬編碼,如不支持再嘗試H.264軟編);
  • ?[RTSP鑒權]支持RTSP鑒權推送;
  • ?[TCP/UDP模式]支持rtp over udp和rtp over tcp兩種傳輸方式;
  • ?[401事件處理]RTSP推送支持401事件上報;
  • ?[視頻格式]支持H.264/H.265(64位庫)編碼;
  • ?[音頻格式]支持AAC編碼;
  • ?[軟硬編碼參數配置]支持gop間隔、幀率、bit-rate設置;
  • ?[軟編碼參數配置]支持軟編碼profile、軟編碼速度、可變碼率設置;
  • ?[多實例推送]支持多實例推送(如同時推送屏幕/攝像頭和外部數據);
  • ?[多分辨率支持]支持攝像頭或屏幕多種分辨率設置;
  • ?[Windows推屏]Windows平臺支持屏幕裁剪、窗口采集、屏幕/攝像頭數據合成等多種模式推送;
  • ?[事件回調]支持各種狀態實時回調;
  • ?[水印]Windows平臺支持文字水印、png水印、實時遮擋,Android平臺支持文字水印、png水印;
  • ?[復雜網絡處理]支持斷網重連等各種網絡環境自動適配;
  • ?[動態碼率]支持根據網絡情況自動調整推流碼率;
  • ?[實時靜音]支持推送過程中,實時靜音/取消靜音;
  • ?[實時快照]支持推流過程中,實時快照;
  • ?[純音頻推流]支持僅采集音頻流并發起推流功能;
  • ?[純視頻推流]支持特殊場景下的純視頻推流功能;
  • ?[降噪]Windows/Android平臺支持降噪處理、自動增益、VAD檢測;
  • ?[回音消除]Android平臺支持實時傳遞遠端PCM數據,方便回音消除處理;
  • ?[外部編碼前視頻數據對接]支持YUV數據對接;
  • ?[外部編碼前音頻數據對接]支持PCM對接;
  • ?[外部編碼后視頻數據對接]支持外部H.264數據對接;
  • ?[外部編碼后音頻數據對接]外部AAC/PCMA/PCMU數據對接;
  • ?[推送端休眠設置]Windows平臺支持休眠接口(設置成休眠模式后CPU會適當降低);
  • ?[擴展錄像功能]完美支持和錄像SDK組合使用,錄像相關功能,可參見”8. Windows/Android/iOS錄像SDK“;
  • ?[服務器兼容]支持支持自建服務器(如Darin Stream Server)。

對應Demo:

  • ?Windows測試程序:SmartPublisherDemo.exe;
  • ?Windows C++工程:WIN-PublisherSDK-CPP-Demo;
  • ?Android工程:SmartPublisherV2;
  • ?iOS工程:SmartiOSPublisherV2。

移動端使用說明不再贅述,點擊查看Windows使用說明

大牛直播RTMP播放器SDK

大牛直播RTMP播放器SDK特點:

在沒測試過大牛直播SDK的RTMP播放器之前,你甚至不相信行業內,RTMP播放器延遲可以穩定的做到1秒以內。

無需贅述,全自研內核,行業內一致認可的跨平臺RTMP直播播放器SDK,功能齊全、高穩定、超低延遲、近200家公司明智之選。

功能支持:

如不單獨說明,系Windows、Android、iOS全平臺支持。

  • ?[支持播放協議]高穩定、超低延遲(一秒內,行業內幾無效果接近的播放端)、業內首屈一指的RTMP直播播放器SDK;
  • ?[多實例播放]支持多實例播放;
  • ?[事件回調]支持網絡狀態、buffer狀態等回調;
  • ?[音視頻加密]Windows平臺支持RTMP推送端加密(AES/SM4(國密))音視頻數據正常播放
  • ?[視頻格式]支持RTMP擴展H.265,H.264;
  • ?[音頻格式]支持AAC/PCMA/PCMU/Speex;
  • ?[H.264/H.265軟解碼]支持H.264/H.265軟解;
  • ?[H.264硬解碼]Windows/Android/iOS支持H.264硬解;
  • ?[H.265硬解]Windows/Android/iOS支持H.265硬解;
  • ?[H.264/H.265硬解碼]Android支持設置Surface模式硬解和普通模式硬解碼;
  • ?[緩沖時間設置]支持buffer time設置;
  • ?[首屏秒開]支持首屏秒開模式;
  • ?[低延遲模式]支持類似于線上娃娃機等直播方案的超低延遲模式設置(公網200~400ms);
  • ?[復雜網絡處理]支持斷網重連等各種網絡環境自動適配;
  • ?[快速切換URL]支持播放過程中,快速切換其他URL,內容切換更快;
  • ?[音視頻多種render機制]Android平臺,視頻:surfaceview/OpenGL ES,音頻:AudioTrack/OpenSL ES;
  • ?[實時靜音]支持播放過程中,實時靜音/取消靜音;
  • ?[實時快照]支持播放過程中截取當前播放畫面;
  • ?[只播關鍵幀]Windows平臺支持實時設置是否只播放關鍵幀;
  • ?[渲染角度]支持0°,90°,180°和270°四個視頻畫面渲染角度設置;
  • ?[渲染鏡像]支持水平反轉、垂直反轉模式設置;
  • ?[實時下載速度更新]支持當前下載速度實時回調(支持設置回調時間間隔);
  • ?[ARGB疊加]Windows平臺支持ARGB圖像疊加到顯示視頻(參看C++的DEMO);
  • ?[解碼前視頻數據回調]支持H.264/H.265數據回調;
  • ?[解碼后視頻數據回調]支持解碼后YUV/RGB數據回調;
  • ?[解碼后視頻數據縮放回調]Windows平臺支持指定回調圖像大小的接口(可以對原視圖像縮放后再回調到上層);
  • ?[解碼前音頻數據回調]支持AAC/PCMA/PCMU/SPEEX數據回調;
  • ?[音視頻自適應]支持播放過程中,音視頻信息改變后自適應;
  • ?[擴展錄像功能]完美支持和錄像SDK組合使用(支持RTMP擴展H.265流錄制,支持PCMA/PCMU/Speex轉AAC后錄制,支持設置只錄制音頻或視頻),錄像相關功能,可參見”Windows/Android/iOS錄像SDK“。

對應Demo:

  • ?Windows測試程序:SmartPlayer.exe;
  • ?Windows C++工程:WIN-PlayerSDK-CPP-Demo;
  • ?Windows C#工程:WIN-PlayerSDK-CSharp-Demo;
  • ?Android工程:SmartPlayerV2;
  • ?iOS工程:SmartiOSPlayerV2。

Demo使用說明

大牛直播sdk-windows-rtmp-rtsp-本地flv播放器使用說明

 

大牛直播RTSP播放器SDK

大牛直播RTSP播放器SDK特點:

無需贅述,全自研內核,行業內一致認可的跨平臺RTSP直播播放器SDK,功能齊全、高穩定、超低延遲,適用于安防、教育、單兵指揮等行業。

功能支持:

如不單獨說明,系Windows、Android、iOS全平臺支持。

  • ?[支持播放協議]高穩定、超低延遲、業內首屈一指的RTSP直播播放器SDK;
  • ?[多實例播放]支持多實例播放;
  • ?[事件回調]支持網絡狀態、buffer狀態等回調;
  • ?[視頻格式]支持H.265、H.264,此外,還支持RTSP MJPEG播放;
  • ?[音頻格式]支持AAC/PCMA/PCMU;
  • ?[H.264/H.265軟解碼]支持H.264/H.265軟解;
  • ?[H.264硬解碼]Windows/Android/iOS支持H.264硬解;
  • ?[H.265硬解]Windows/Android/iOS支持H.265硬解;
  • ?[H.264/H.265硬解碼]Android支持設置Surface模式硬解和普通模式硬解碼;
  • ?[RTSP模式設置]支持RTSP TCP/UDP模式設置;
  • ?[RTSP TCP/UDP自動切換]支持RTSP TCP、UDP模式自動切換;
  • ?[RTSP超時設置]支持RTSP超時時間設置,單位:秒;
  • ?[RTSP 401認證處理]支持上報RTSP 401事件,如URL攜帶鑒權信息,會自動處理;
  • ?[緩沖時間設置]支持buffer time設置;
  • ?[首屏秒開]支持首屏秒開模式;
  • ?[復雜網絡處理]支持斷網重連等各種網絡環境自動適配;
  • ?[快速切換URL]支持播放過程中,快速切換其他URL,內容切換更快;
  • ?[音視頻多種render機制]Android平臺,視頻:surfaceview/OpenGL ES,音頻:AudioTrack/OpenSL ES;
  • ?[實時靜音]支持播放過程中,實時靜音/取消靜音;
  • ?[實時快照]支持播放過程中截取當前播放畫面;
  • ?[只播關鍵幀]Windows平臺支持實時設置是否只播放關鍵幀;
  • ?[渲染角度]支持0°,90°,180°和270°四個視頻畫面渲染角度設置;
  • ?[渲染鏡像]支持水平反轉、垂直反轉模式設置;
  • ?[實時下載速度更新]支持當前下載速度實時回調(支持設置回調時間間隔);
  • ?[解碼前視頻數據回調]支持H.264/H.265數據回調;
  • ?[解碼后視頻數據回調]支持解碼后YUV/RGB數據回調;
  • ?[解碼前音頻數據回調]支持AAC/PCMA/PCMU數據回調;
  • ?[音視頻自適應]支持播放過程中,音視頻信息改變后自適應;
  • ?[擴展錄像功能]完美支持和錄像SDK組合使用(支持RTSP H.265流錄制,支持PCMA/PCMU轉AAC后錄制,支持設置只錄制音頻或視頻),錄像相關功能,可參見”Windows/Android/iOS錄像SDK“。

對應Demo:

  • ?Windows測試程序:SmartPlayer.exe;
  • ?Windows C++工程:WIN-PlayerSDK-CPP-Demo;
  • ?Windows C#工程:WIN-PlayerSDK-CSharp-Demo;
  • ?Android工程:SmartPlayerV2;
  • ?iOS工程:SmartiOSPlayerV2。

Demo使用說明

大牛直播sdk-windows-rtmp-rtsp-本地flv播放器使用說明

一對一互動SDK

大牛直播一對一互動SDK涵蓋Windows、Android和iOS平臺。

目前市面上大多一對一互動都是基于WebRTC,缺點如下:

  1. 服務器部署非常復雜,不利于私有部署,在一些私密性高的場景下,無法使用,如公安、市政等體系;
  2. 傳輸基于UDP,很難保證傳輸質量,由于UDP是不可靠的傳輸協議,在復雜的公網網絡環境下,各種突發流量、偶爾的傳輸錯誤、網絡抖動、超時等等都會引起丟包異常,都會在一定程度上影響音視頻通信的質量;
  3. 難以應對復雜的互聯網環境,如跨區跨運營商、低帶寬、高丟包等場景;
  4. 整個框架體系不夠靈活,代碼復雜度高,行話說的好:從demo到實用,中間還差1萬個WebRTC

RTMP/RTSP一對一互動SDK有以下優點:

  • ?基于官方現有RTMP、RTSP推送、或內置RTSP服務、播放SDK,產品穩定度高,行業內首屈一指的超低延遲特性;
  • ?加入噪音抑制、回音消除、自動增益控制等特性,確保通話效果;
  • ?采用通用的RTMP和RTSP服務器,如nginx、SRS或 Darwin Stream Server(原生版本),更有利于私有部署;
  • ?支持H.264的擴展SEI消息發送機制;
  • ?支持H.265編碼(Windows 64位庫,Android/iOS硬編碼)和H.264可變碼率設定,換句話說,之前大牛直播SDK推送端支持的功能,都可以同步支持;
  • ?支持H.265解碼,直播播放器支持的功能,一對一互動模塊都可以有選擇的支持;
  • ?Windows平臺支持雙流合成大小屏錄制;
  • ?Windows支持攝像頭、屏幕合成、水印等各種組合模式,擴展度高;
  • ?適用于應急指揮、教育培訓等領域;
  • ?支持RTMP擴展AES/SM4加解密,確保音視頻數據安全性;

對應Demo:

  • ?Windows C++工程:集成可參考WIN-PublisherSDK-CPP-Demo和WIN-PlayerSDK-CPP-Demo,或相應C# demo;
  • ?Android工程:SmartEchoCancellationV2;
  • ?iOS工程:SmartiOSEchoCancellation。

本地FLV播放SDK

大牛直播本地FLV播放SDK,目前覆蓋Windows平臺。

功能支持:

  1. 視頻:H.264;
  2. 音頻:AAC;
  3. 支持本地flv文件播放(支持獲取flv文件的duration(時長);
  4. 支持顯示當前播放位置;
  5. 支持開始播放或播放過程中seek(跳轉播放位置),也許是行業內seek最快的flv點播播放器);
  6. 可通過回調本地FLV音視頻數據幀,配合RTMP推送模塊,實現本地FLV文件的實時RTMP流轉發。

視沃科技(大牛直播SDK)RTMP推送-RTSP/RTMP直播SDK

視沃科技-大牛直播SDK?daniulive.com

始于2014年,國內外為數不多致力于極致體驗的超強全自研跨平臺(windows/android/iOS)流媒體內核,通過模塊化自由組合,支持實時RTMP推流、RTMP/RTSP直播播放(支持RTSP/RTMP H.265)、實時錄像、多路流媒體轉發、音視頻導播、動態視頻合成、音頻混音、互動直播、內置輕量級RTSP服務等,比快更快,業界真正靠譜的超低延遲直播SDK(1秒內,低延遲模式下200~400ms)。

適用于在線教育、無紙化推屏/會議、智慧教室、直播答題、智能可視門禁對講、智慧安防、智能家居、物聯網、智能車載、傳統硬件領域、超低延遲娃娃機抓取播放方案、媒體移動直播、應急指揮調度(針對保險、城管、交警、消防、公安等職能管理部門的單兵應急執法系統)、可視化購物、遠程專家診斷、可視化巡檢、(如電信/電力線路/鐵路沿線/水利設施/油田/消防設施巡檢)、移動視頻安防監控,企業內訓、金融在線直播室、微信直播、監控對接、活動現場直播、游戲直播、秀場直播等場景。

latest release note

除此之外,大牛直播SDK播放端,支持APICloudReact Native二次封裝,并且全平臺支持Unity3D平臺,也可能是Unity3D平臺下首款真正高穩定、超低延遲的rtmp/rtsp直播播放器。

android/iOS播放器SDK(V2)APICloud調用說明

windows/android/iOS播放器SDK(V2)Unity3D調用說明(更新于2018/10/31)

大牛直播SDK基于unity3d平臺的rtmp/rtsp直播播放端SDK視頻演示

Unity3D-Windows播放端APP下載(更新于2018/09/04)

Unity3D-Android播放端APK下載(更新于2018/10/24)

Windows端

  • ?RTMP直播推流SDK?rtmp推送SDK(支持同時推多路url,支持RTMP擴展H.265推送(64位庫));
  • ?RTMP/RTSP直播播放器SDK?業內首屈一指的rtmp/rtsp超低延遲直播播放器SDK(支持RTMP H.265擴展播放);
  • ?Unity3D RTMP/RTSP直播播放器SDK?業內首家Windows支持Unity3D的超低延遲RTMP/RTSP直播播放器SDK,支持快照、錄像、實時靜音、view旋轉、快速切換URL等特性;
  • ?RTMP/RTSP多路流媒體轉RTMP推送SDK?支持同時多路拉取rtmp/rtsp流/本地flv文件,并分別轉發到服務器,支持轉發過程中,拉取的rtsp/rtmp或本地flv文件實時內容切換,業內為數不多支持RTSP/RTMP H.265拉流轉發的SDK(提供配套RTMP擴展H.265服務器);
  • ?輕量級RTSP服務SDK?為滿足內網無紙化/電子教室等內網超低延遲需求,避免讓用戶配置單獨的服務器,大牛直播SDK在推送端支持輕量級RTSP服務SDK,推送端SDK支持的功能,內置輕量級RTSP服務SDK后,功能繼續支持,windows端64位庫支持RTSP H.265視頻輸出;
  • ?內網RTSP網關SDK?內網RTSP網關SDK,系內置輕量級RTSP服務SDK擴展,完成外部RTSP/RTMP數據拉取并注入到輕量級RTSP服務SDK工作,多個內網客戶端直接訪問內網輕量級RTSP服務獲取公網數據,無需部署單獨的服務器,支持RTSP/RTMP H.265數據接入;
  • ?導播SDK?數據源:1. rtmp/rtsp音視頻流;2. 本地屏幕/攝像頭/音頻數據;3.本地flv文件;多路流合成一路實時導播推送;
  • ?錄像SDK?支持拉取rtmp/rtsp流實時錄像模塊/實時快照功能,支持純音頻、純視頻、音視頻錄制模式,支持音頻(PCMU/PCMA,Speex等)轉AAC后再錄像,業內為數不多的支持RTSP/RTMP H.265錄制到MP4文件的錄像SDK;
  • ?[互動SDK] Windows一對一互動(可windows與windows/android互動);
  • ?連麥SDK?以標準協議為基礎,完美支持Windows連麥;
  • ?[點播播放器SDK] 支持本地flv文件播放(支持獲取flv文件的duration(時長);支持顯示當前播放位置;支持開始播放或播放過程中seek(跳轉播放位置),也許是行業內seek最快的flv點播播放器);
  • ?SEI擴展數據發送/接收SDK?支持推送端通過H.264 SEI信息擴展,實時傳輸文本/二進制數據信息(如實時字幕/時間戳/題目分發/公告廣播等),播放端做相應解析和回顯;
  • ?視頻處理SDK?屏幕/多攝像頭/水印/遮擋區域多層自由合成模塊;
  • ?音頻處理SDK?多路混音、回音消除、噪音抑制、自動增益、VAD檢測模塊;

Android端

  • ?RTMP直播推流端SDK?Android屏幕、攝像頭RTMP推流SDK;
  • ?RTMP/RTSP直播播放器SDK?業內首屈一指的rtmp/rtsp超低延遲直播播放器SDK(支持RTMP H.265擴展播放);
  • ?Unity3D RTMP/RTSP直播播放器SDK?業內首家Android支持Unity3D的超低延遲RTMP/RTSP直播播放器SDK,支持快照、錄像、實時靜音、view旋轉、快速切換URL等特性;
  • ?錄像SDK?支持拉取rtmp/rtsp流實時錄像模塊/實時快照功能,支持純音頻、純視頻、音視頻錄制模式,支持音頻(PCMU/PCMA,Speex等)轉AAC后再錄像,業內為數不多的支持RTSP/RTMP H.265錄制到MP4文件的錄像SDK;
  • ?RTMP/RTSP多路流媒體轉RTMP推送SDK?支持實時拉取的rtmp/rtsp流轉發到指定rtmp url;
  • ?輕量級RTSP服務SDK?為滿足內網無紙化/電子教室等內網超低延遲需求,避免讓用戶配置單獨的服務器,大牛直播SDK在推送端支持輕量級RTSP服務SDK,推送端SDK支持的功能,內置輕量級RTSP服務SDK后,功能繼續支持;
  • ?[互動SDK] Android一對一互動(可android與windows/android/iOS互動);
  • ?SEI擴展數據發送/接收SDK?支持推送端通過H.264 SEI信息擴展,實時傳輸文本/二進制數據信息(如實時字幕/時間戳/題目分發/公告廣播等),播放端做相應解析和回顯;
  • ?視頻處理SDKAndroid文字水印、png圖片水印;
  • ?音頻處理SDKAndroid回音消除、噪音抑制、自動增益、VAD檢測模塊;

iOS端

  • ?RTMP直播推流端SDK?iOS屏幕(基于ReplayKit)、攝像頭RTMP推流SDK;
  • ?RTMP/RTSP直播播放器SDK?業內首屈一指的rtmp/rtsp超低延遲直播播放器SDK(支持RTMP H.265擴展播放);
  • ?Unity3D RTMP/RTSP直播播放器SDK?業內首家iOS支持Unity3D的超低延遲RTMP/RTSP直播播放器SDK,支持快照、錄像、實時靜音、view旋轉、快速切換URL等特性;
  • ?錄像SDK?支持拉取rtmp/rtsp流實時錄像模塊/實時快照功能,支持純音頻、純視頻、音視頻錄制模式,支持音頻(PCMU/PCMA,Speex等)轉AAC后再錄像,業內為數不多的支持RTSP/RTMP H.265錄制到MP4文件的錄像SDK;
  • ?RTMP/RTSP多路流媒體轉RTMP推送SDK?支持實時拉取的rtmp/rtsp流轉發到指定rtmp url;
  • ?輕量級RTSP服務SDK?為滿足內網無紙化/電子教室等內網超低延遲需求,避免讓用戶配置單獨的服務器,大牛直播SDK在推送端支持輕量級RTSP服務SDK,推送端SDK支持的功能,內置輕量級RTSP服務SDK后,功能繼續支持;
  • ?SEI擴展數據發送/接收SDK?支持推送端通過H.264 SEI信息擴展,實時傳輸文本/二進制數據信息(如實時字幕/時間戳/題目分發/公告廣播等),播放端做相應解析和回顯;

本地下載

很多開發者反應,由于項目龐大,github下載整個工程很慢,我們已經把相關demo文件和使用說明,全部上傳到QQ群共享:

或者直接從私有服務器下載(Windows提供C#/C++ demo, android提供android studio demo,iOS提供xcode demo):

大牛直播SDK相關demo本地下載

NOTE:?Windows平臺,以C++ SDK Demo為最新,C# Demo更新速度稍滯于C++ Demo。

大牛直播SDK集成和調用說明

大牛直播SDK Demo使用說明

上層源碼目錄

  1. android推流 SmartPublisherV2https://github.com/daniulive/SmarterStreaming/tree/master/SourceCode/AndroidStudio/SmartPublisherV2
  2. android推流 SmartServicePublisherV2(后臺service推送屏幕)https://github.com/daniulive/SmarterStreaming/tree/master/SourceCode/AndroidStudio/SmartServicePublisherV2
  3. android推流 SmartServiceCameraPublisherV2(后臺service推送攝像頭)https://github.com/daniulive/SmarterStreaming/tree/master/SourceCode/AndroidStudio/SmartServiceCameraPublisherV2
  4. android一對一回音消除 SmartEchoCancellationV2https://github.com/daniulive/SmarterStreaming/tree/master/SourceCode/AndroidStudio/SmartEchoCancellationV2
  5. android播放器 SmartPlayerV2:https://github.com/daniulive/SmarterStreaming/tree/master/SourceCode/AndroidStudio/SmartPlayerV2
  6. android轉發-錄像-播放三合一 SmartRelayDemoV2:https://github.com/daniulive/SmarterStreaming/tree/master/SourceCode/AndroidStudio/SmartRelayDemoV2
  7. iOS推流 SmartiOSPublisherV2:https://github.com/daniulive/SmarterStreaming/tree/master/SourceCode/IOS/SmartiOSPublisherV2
  8. iOS后臺推屏 SmartiOSScreenPublisherV2:https://github.com/daniulive/SmarterStreaming/tree/master/SourceCode/IOS/SmartiOSScreenPublisherV2
  9. iOS播放器 SmartiOSPlayerV2:https://github.com/daniulive/SmarterStreaming/tree/master/SourceCode/IOS/SmartiOSPlayerV2
  10. iOS轉發-錄像-播放三合一 SmartiOSRelayDemoV2:https://github.com/daniulive/SmarterStreaming/tree/master/SourceCode/IOS/SmartiOSRelayDemoV2

功能支持


1. Windows視頻采集處理SDK

  1. 支持視頻源
  • ?支持Windows屏幕采集、屏幕裁剪特定窗口采集、攝像頭采集、擴展外部H.264數據對接;
  1. 攝像頭和屏幕合成
  • ?[攝像頭和屏幕實時切換]支持推送過程中,攝像頭和屏幕互相切換,單畫面顯示攝像頭或屏幕;
  • ?[攝像頭疊加到屏幕] 支持攝像頭按照設置坐標,疊加到屏幕指定位置,并支持實時關閉疊加層;
  • ?[屏幕疊加到攝像頭] 支持屏幕按照設定坐標,疊加到攝像頭指定位置,并支持實時關閉疊加層;
  1. 水印和透明度遮擋
  • ?[實時水印]支持動態水印設置,完美支持文字水印、實時時間水印和圖片水印
  • ?[透明度]可以設置透明度處理(設置遮蓋);
  1. 對應Demo:
  • ?測試程序:SmartPublisherDemo.exe;
  • ?C++工程:WIN-PublisherSDK-CPP-Demo;
  • ?C#工程:WIN-PublisherSDK-CSharp-Demo。

2. Windows音頻采集處理SDK

  1. 支持音頻源
  • ?支持Windows采集麥克風揚聲器和外部AAC, Speex WB, PCMA, PCMU數據接口輸入;
  1. 音頻合成
  • ?[音頻]支持揚聲器和麥克風音頻混音輸出(同時選擇“采集揚聲器”和“采集麥克風”);
  1. 音頻處理
  • ?支持音頻“端點檢測(VAD)”,自適應碼流,音頻碼流更節省;
  • ?支持回音消除功能;
  • ?支持噪音抑制功能;
  • ?支持自動增益控制。
  1. 對應Demo:
  • ?測試程序:SmartPublisherDemo.exe;
  • ?C++工程:WIN-PublisherSDK-CPP-Demo;
  • ?C#工程:WIN-PublisherSDK-CSharp-Demo。

3. Windows/Android/iOS RTMP直播推流SDK

如不單獨說明,系Windows、Android、iOS全平臺支持。

  • ?[視頻采集處理]Windows平臺涵蓋“Windows視頻采集處理SDK”功能;
  • ?[音頻采集處理]Windows平臺涵蓋“Windows音頻采集處理SDK”功能;
  • ?[本地預覽]Windows平臺支持攝像頭/屏幕/合成數據實時預覽功能,Android/iOS平臺支持本地前后置攝像頭預覽;
  • ?[攝像頭反轉/旋轉]Windows平臺支持攝像頭水平反轉、垂直反轉、0°/90°/180°/270°旋轉;
  • ?[RTMP推流]超低延時的RTMP協議直播推流SDK(Windows支持RTMP擴展H.265推送);
  • ?[視頻格式]Windows平臺支持H.264/H.265編碼,Android/iOS平臺支持H.264編碼;
  • ?[音頻格式]Windows/Android/iOS平臺支持AAC編碼,Windows/Android平臺支持Speex編碼;
  • ?[音頻編碼]Windows/Android平臺支持Speex推送、Speex編碼質量設置;
  • ?[H.264硬編碼]Android/iOS支持H.264硬編碼;
  • ?[硬編碼碼自適應]Android/iOS平臺支持硬編碼自適應,如檢測到硬編碼不支持,自動切換到軟編;
  • ?[編碼參數配置]支持gop間隔、幀率、bit-rate、軟編碼profile、軟編碼速度設置;
  • ?[多實例推送]支持多實例推送(如同時推送屏幕/攝像頭和外部數據);
  • ?[RTMP擴展H.265]Windows推送SDK支持RTMP擴展H.265推送,針對攝像頭采集編碼,使用H.265可變碼率,帶寬大幅節省,效果直逼傳統H.265編碼攝像頭;
  • ?[橫豎屏推流]Android/iOS平臺支持支持橫屏、豎屏推流;
  • ?[多分辨率支持]支持攝像頭或屏幕多種分辨率設置;
  • ?[Windows推屏]支持屏幕裁剪、窗口采集、屏幕/攝像頭數據合成等多種模式推送;
  • ?[移動端推屏]Android平臺支持后臺service推送攝像頭或屏幕(推送屏幕需要5.0+版本);
  • ?[移動端推屏]iOS平臺支持后臺推送屏幕(基于ReplayKit,需要iOS 10.0+版本);
  • ?[事件回調]支持各種狀態實時回調;
  • ?[水印]Windows平臺支持文字水印、png水印、實時遮擋,Android平臺支持文字水印、png水印;
  • ?[RTMP推送模式]支持RTMP推送 live|record模式設置(需服務器支持);
  • ?[鏡像]Android/iOS平臺支持前置攝像頭實時鏡像功能;
  • ?[前后攝像頭實時切換]Android/iOS平臺支持采集過程中,前后攝像頭切換;
  • ?[復雜網絡處理]支持斷網重連等各種網絡環境自動適配;
  • ?[動態碼率]支持根據網絡情況自動調整推流碼率;
  • ?[實時靜音]支持推送過程中,實時靜音/取消靜音;
  • ?[實時快照]支持推流過程中,實時快照;
  • ?[純音頻推流]支持僅采集音頻流并發起推流功能;
  • ?[純視頻推流]支持特殊場景下的純視頻推流功能;
  • ?[降噪]Windows/Android平臺支持環境音、手機干擾等引起的噪音降噪處理、自動增益、VAD檢測;
  • ?[回音消除]android支持實時傳遞遠端PCM數據,方便回音消除處理;
  • ?[外部編碼前視頻數據對接]支持YUV數據對接;
  • ?[外部編碼前音頻數據對接]支持PCM對接;
  • ?[外部編碼后視頻數據對接]支持外部H.264數據對接;
  • ?[外部編碼后音頻數據對接]外部AAC/PCMA/PCMU/SPEEX數據對接;
  • ?[編碼后數據輸出]Android平臺支持輸出編碼后的H264/AAC數據到上層,方便對接第三方平臺(如GB28181)對接(接口說明和demo請點擊以下鏈接);
  • ?[擴展錄像功能]完美支持和錄像SDK組合使用,錄像相關功能,可參見”8. Windows/Android/iOS錄像SDK“;
  • ?[基礎美顏]iOS平臺自帶基礎美顏功能;
  • ?[裁剪模式]Android/iOS平臺支持特定分辨率攝像頭裁剪模式設置;
  • ?[服務器兼容]支持支持自建服務器(如Nginx、SRS)或CDN。

對應Demo:

  • ?Windows測試程序:SmartPublisherDemo.exe;
  • ?Windows C++工程:WIN-PublisherSDK-CPP-Demo;
  • ?Windows C#工程:WIN-PublisherSDK-CSharp-Demo;
  • ?Android工程:SmartPublisherV2;
  • ?iOS工程:SmartiOSPublisherV2。

4. Windows/Android/iOS RTMP、RTSP直播播放器SDK

如不單獨說明,系Windows、Android、iOS全平臺支持。

  • ?[支持播放協議]高穩定、超低延遲(一秒內,行業內幾無效果接近的播放端)、業內首屈一指的RTMP/RTSP直播播放器SDK;
  • ?[多實例播放]支持多實例播放(如同時播放多路RTMP/RTSP流);
  • ?[事件回調]支持網絡狀態、buffer狀態等回調;
  • ?[視頻格式]支持RTSP H.265、RTMP擴展H.265,RTSP/RTMP H.264;
  • ?[音頻格式]RTMP/RTSP支持AAC/PCMA/PCMU,此外RTMP還支持Speex;
  • ?[H.264/H.265軟解碼]支持H.264/H.265軟解;
  • ?[H.264硬解碼]Android/iOS支持H.264硬解;
  • ?[H.265硬解]Android支持H.265硬解;
  • ?[H.264/H.265硬解碼]Android支持設置Surface模式硬解和普通模式硬解碼;
  • ?[硬解碼自適應]Android/iOS平臺支持硬解碼碼自適應,如檢測到硬解碼不支持,自動切換到軟解;
  • ?[RTSP模式設置]支持RTSP TCP/UDP模式設置;
  • ?[RTSP TCP/UDP自動切換]支持RTSP TCP、UDP模式自動切換;
  • ?[RTSP超時設置]支持RTSP超時時間設置,單位:秒;
  • ?[RTSP 401認證處理]支持上報RTSP 401事件,如URL攜帶鑒權信息,會自動處理;
  • ?[緩沖時間設置]支持buffer time設置;
  • ?[首屏秒開]支持首屏秒開模式;
  • ?[低延遲模式]支持類似于線上娃娃機等直播方案的超低延遲模式設置(公網200~400ms);
  • ?[復雜網絡處理]支持斷網重連等各種網絡環境自動適配;
  • ?[快速切換URL]支持播放過程中,快速切換其他URL,內容切換更快;
  • ?[音視頻多種render機制]Android平臺,視頻:surfaceview/OpenGL ES,音頻:AudioTrack/OpenSL ES;
  • ?[實時靜音]支持播放過程中,實時靜音/取消靜音;
  • ?[實時快照]支持播放過程中截取當前播放畫面;
  • ?[渲染角度]支持0°,90°,180°和270°四個視頻畫面渲染角度設置;
  • ?[渲染鏡像]支持水平反轉、垂直反轉模式設置;
  • ?[實時下載速度更新]支持當前下載速度實時回調(支持設置回調時間間隔);
  • ?[解碼前視頻數據回調]支持H.264/H.265數據回調;
  • ?[解碼后視頻數據回調]支持解碼后YUV/RGB數據回調;
  • ?[解碼前音頻數據回調]支持AAC/PCMA/PCMU/SPEEX數據回調;
  • ?[音視頻自適應]支持播放過程中,音視頻信息改變后自適應;
  • ?[擴展錄像功能]完美支持和錄像SDK組合使用,錄像相關功能,可參見”8. Windows/Android/iOS錄像SDK“;
  • ?[全屏]Windows平臺雙擊畫面進入全屏模式;
  • ?[Windows本地FLV播放器]支持本地FLV文件播放(支持獲取FLV文件的duration(時長);支持顯示當前播放位置;
  • ?[Windows本地FLV播放器]支持開始播放或播放過程中seek(跳轉播放位置),也許是行業內seek最快的flv點播播放器)。

對應Demo:

  • ?Windows測試程序:SmartPlayer.exe;
  • ?Windows C++工程:WIN-PlayerSDK-CPP-Demo;
  • ?Windows C#工程:WIN-PlayerSDK-CSharp-Demo;
  • ?Android工程:SmartPlayerV2;
  • ?iOS工程:SmartiOSPlayerV2。

5. Windows/Android/iOS內置輕量級RTSP服務SDK

如不單獨說明,系Windows、Android、iOS全平臺支持。

  • ?[基礎功能]支持Windows/Android/iOS平臺RTMP直播SDK除推送RTMP外的所有常規功能;
  • ?[音頻格式]AAC;
  • ?[視頻格式]H.264、H.265;
  • ?[協議類型]RTSP;
  • ?[端口設置]支持RTSP端口設置;
  • ?[鑒權設置]支持RTSP鑒權用戶名、密碼設置;
  • ?[獲取session連接數]支持獲取當前RTSP服務會話連接數;
  • ?[多服務支持]支持同時創建多個內置RTSP服務;
  • ?[H.265支持]Windows內置rtsp server支持發布H.265視頻(64位庫);
  • ?[RTSP url回調]支持設置后的rtsp url通過event回調到上層。

對應Demo:

  • ?Windows測試程序:SmartPublisherDemo.exe;
  • ?Windows C++工程:WIN-PublisherSDK-CPP-Demo;
  • ?Windows C#工程:WIN-PublisherSDK-CSharp-Demo;
  • ?Android工程:SmartPublisherV2;
  • ?iOS工程:SmartiOSPublisherV2。

6. Windows內網RTSP網關SDK

內網RTSP網關SDK,系內置輕量級RTSP服務SDK擴展,完成外部RTSP/RTMP數據拉取并注入到輕量級RTSP服務SDK工作,多個內網客戶端直接訪問內網輕量級RTSP服務獲取公網數據,無需部署單獨的服務器,支持RTSP/RTMP H.265數據接入。 簡單來說:內置輕量級RTSP服務SDK和內置RTSP網關SDK的區別在于數據來源不同,內置輕量級RTSP服務SDK數據來源于終端設備自帶攝像頭數據/屏幕數據/外部編碼前后數據,內置RTSP網關SDK的數據源是RTSP/RTMP流數據。

  • ?[音頻格式]AAC;
  • ?[視頻格式]H.264、H.265;
  • ?[接入協議]支持內外網RTMP/RTSP流接入;
  • ?[輸出協議]RTSP,拉取的RTSP/RTMP流,注入輕量級RTSP服務SDK;
  • ?[音頻轉碼]支持音頻(PCMU/PCMA,Speex等)轉AAC后注入;
  • ?[端口設置]支持RTSP端口設置;
  • ?[鑒權設置]支持RTSP鑒權用戶名、密碼設置;
  • ?[獲取session連接數]支持獲取當前RTSP服務會話連接數;
  • ?[多服務支持]支持同時創建多個內置RTSP服務;
  • ?[H.265支持]Windows內置rtsp server支持發布H.265視頻(64位庫);
  • ?[RTSP url回調]支持設置后的rtsp url通過event回調到上層;

對應Demo:

  • ?Windows測試程序:SmartStreamRelayDemo.exe;
  • ?Windows C++工程:WIN-RelaySDK-CPP-Demo;
  • ?Windows C#工程:WIN-RelaySDK-CSharp-Demo。

7. Windows/Android/iOS RTMP/RTSP多路流媒體轉RTMP推送SDK

如不單獨說明,系Windows、Android、iOS全平臺支持。

  • ?[拉流]支持拉取RTSP流;
  • ?[拉流]支持拉取RTMP流;
  • ?[預覽]支持拉取到的RTMP/RTSP隨時本地預覽、關閉預覽;
  • ?[拉流音頻調節]支持拉取的RTMP/RTSP流靜音;
  • ?[音頻轉碼]支持拉取的RTMP/RTSP的PCMA/PCMU/SPEEX音頻格式轉AAC后再轉發到RTMP服務器;
  • ?[url切換]支持轉發過程中,拉取的RTMP/RTSP或本地FLV文件實時內容切換
  • ?[轉發]超低延遲轉發拉取的rtsp/rtmp流到rtmp server;
  • ?[H.265支持]業內首家支持RTSP/RTMP H.265轉RTMP推送的SDK(提供配套RTMP擴展H.265服務器);

對應Demo:

  • ?Windows測試程序:SmartStreamRelayDemo.exe;
  • ?Windows C++工程:WIN-RelaySDK-CPP-Demo;
  • ?Windows C#工程:WIN-RelaySDK-CSharp-Demo;
  • ?Android工程:SmartRelayDemoV2;
  • ?iOS工程:SmartiOSRelayDemoV2。

8. Windows導播SDK

  • ?[拉流]支持拉取RTSP流;
  • ?[拉流]支持拉取RTMP流;
  • ?[混音合成]支持本地采集到屏幕或攝像頭數據,和遠程拉取得RTSP或RTMP流做合成、混音輸出;
  • ?[導播]支持導播過程中,隨時切斷某一路音視頻或音頻;
  • ?[混音]支持音頻混音(同時選擇“采集麥克風”+“采集揚聲器”);
  • ?[合成]多路流合成一路流后,推送到RTMP服務器;
  • ?[擴展錄像快照]多路合成后的流,支持本地錄像、快照。

對應Demo:

  • ?測試程序:SmartMixStreamDemo.exe;
  • ?C++工程:WIN-MixStreamSDK-CPP-Demo;

9. Windows/Android/iOS錄像SDK

  • ?[拉流]支持拉取RTSP流錄像;
  • ?[拉流]支持拉取RTMP流錄像;
  • ?[推流端錄像]支持推送端同步錄像;
  • ?[邏輯分離]大牛直播錄像SDK不同于普通錄像接口,更智能,和推送、播放、轉發、內置輕量級RTSP服務SDK功能完全分離,支持隨時錄像;
  • ?[url切換]在錄像過程中,支持切換不同URL,如兩個URL配置一致,則可以錄制到同一個MP4文件,如不一致,可自動分割到下一個文件;
  • ?[參數設置]支持設置單個錄像文件大小、錄像路徑等,并支持純音頻、純視頻、音視頻錄制模式;
  • ?[音頻轉碼]支持音頻(PCMU/PCMA,Speex等)轉AAC后再錄像;
  • ?[265支持]支持RTSP/RTMP H.265錄制到MP4文件;
  • ?[推送端265錄像]Windows推送SDK支持H265錄像;
  • ?[事件回調]從開始錄像,到錄像結束均有event callback上來,網絡堵塞、音視頻同步均做了非常友好的處理。

對應Demo:

  • ?Windows測試程序:SmartPlayer.exe;
  • ?Windows C++工程:WIN-PlayerSDK-CPP-Demo;
  • ?Windows C#工程:WIN-PlayerSDK-CSharp-Demo;
  • ?測試程序:SmartPublisherDemo.exe;
  • ?C++工程:WIN-PublisherSDK-CPP-Demo;
  • ?C#工程:WIN-PublisherSDK-CSharp-Demo。
  • ?Android工程:SmartPlayerV2;
  • ?iOS工程:SmartiOSPlayerV2;
  • ?Android工程:SmartPublisherV2;
  • ?iOS工程:SmartiOSPublisherV2。

10. Windows/Android/iOS SEI擴展數據發送/接收SDK

  • ?[RTSP SEI]支持內置RTSP服務SDK攜帶SEI擴展信息(H.264);
  • ?[RTMP SEI]支持RTMP推送SDK攜帶SEI擴展信息(H.264);
  • ?[自定義數據]持發送自定義用戶數據(如自定義utf8字符串);
  • ?[二進制數據]支持發送二進制數據;
  • ?[播放端解析]RTSP/RTMP直播播放端SDK支持utf8文本、二進制、和原SEI數據解析。

對應Demo:

  • ?Windows測試程序:SmartPlayer.exe;
  • ?Windows C++工程:WIN-PlayerSDK-CPP-Demo;
  • ?Windows C#工程:WIN-PlayerSDK-CSharp-Demo;
  • ?測試程序:SmartPublisherDemo.exe;
  • ?C++工程:WIN-PublisherSDK-CPP-Demo;
  • ?C#工程:WIN-PublisherSDK-CSharp-Demo。
  • ?Android工程:SmartPlayerV2;
  • ?iOS工程:SmartiOSPlayerV2;
  • ?Android工程:SmartPublisherV2;
  • ?iOS工程:SmartiOSPublisherV2。

編譯注意事項

  • iOS平臺支持真機和模擬器編譯運行.
  • iOS播放端編譯時找不到 libSmartPlayerSDK.a 時,請先到 SmartiOSPlayer/SmartiOSPlayer/libs 目錄, 解壓libSmartPlayerSDK.zip.
  • iOS推送端編譯時找不到 libSmartPublisherSDK.a 時,請先到 SmartiOSPublisher/SmartiOSPublisher/libs 目錄, 解壓libSmartPublisherSDK.zip.
  • 未授權版本,限制app-name,如果需要集成到自己工程里面調試,可以用以下名字:
Windows推送端:SmartPublisherDemo
Windows播放端:SmartPlayer
Windows轉發端:SmartStreamRelayDemo
Windows合流導播端:SmartMixStreamDemo
android推送端:SmartPublisherSDKDemo
android后臺Service推送:SmartServicePublisherSDKDemo
android一對一互動:SmartEchoCancellation
android播放器:SmartPlayerSDKDemo
iOS推送端:SmartiOSPublisher
iOS轉發端:SmartiOSRelayDemo
iOS播放器:SmartiOSPlayer
  • 集成到自己工程,如何改名字(以推送端為例):
android:strings.xml:
<string name="app_name">SmartPublisherSDKDemo</string>
iOS:Info.plist-->右鍵Open As-->Source Code,添加或者編輯
<key>CFBundleName</key>	
<string>SmartiOSPublisher</string>

聯系我們

點擊查看聯系方式

QQ交流群:

大牛直播SDK技術交流群1:499687479

大牛直播SDK技術交流群2:294891451

內網RTSP網關SDK

內網RTSP網關SDK,系內置輕量級RTSP服務SDK擴展,完成外部RTSP/RTMP數據拉取并注入到輕量級RTSP服務SDK工作,多個內網客戶端直接訪問內網輕量級RTSP服務獲取公網數據,無需部署單獨的服務器,支持RTSP/RTMP H.265數據接入。

簡單來說:內置輕量級RTSP服務SDK和內置RTSP網關SDK的區別在于數據來源不同,內置輕量級RTSP服務SDK數據來源于終端設備自帶攝像頭數據/屏幕數據/外部編碼前后數據,內置RTSP網關SDK的數據源是RTSP/RTMP流數據。

  • ?[音頻格式]AAC;
  • ?[視頻格式]H.264、H.265;
  • ?[接入協議]支持內外網RTMP/RTSP流接入;
  • ?[輸出協議]RTSP,拉取的RTSP/RTMP流,注入輕量級RTSP服務SDK;
  • ?[傳輸模式]Windows支持單播組播模式,Android/iOS平臺支持單播模式;
  • ?[音頻轉碼]支持音頻(PCMU/PCMA,Speex等)轉AAC后注入;
  • ?[端口設置]支持RTSP端口設置;
  • ?[鑒權設置]支持RTSP鑒權用戶名、密碼設置;
  • ?[獲取session連接數]支持獲取當前RTSP服務會話連接數;
  • ?[多服務支持]支持同時創建多個內置RTSP服務;
  • ?[H.265支持]Windows內置rtsp server支持發布H.265視頻(64位庫);
  • ?[RTSP url回調]支持設置后的rtsp url通過event回調到上層;

對應Demo:

  • ?Windows測試程序:SmartStreamRelayDemo.exe;
  • ?Windows C++工程:WIN-RelaySDK-CPP-Demo;
  • ?Windows C#工程:WIN-RelaySDK-CSharp-Demo;
  • ?iOS工程:SmartiOSRelayDemoV2.

基本使用步驟:

  1. 點擊“配置查看Rtsp服務”按鈕,啟動rtsp服務;
  2. 輸入需要拉流的rtsp或rtmp地址;
  3. 點擊拉流,獲取rtsp或rtsp流數據;
  4. 點擊“發送rtsp流”,即可把數據注入內網rtsp網關sdk;
  5. 發送成功后,會回調可用來播放的內網rtsp url;
  6. 播放端,輸入步驟5回調的rtsp地址,完成拉流播放;
  7. 如果查看連接的內網播放session數,點擊“配置查看Rtsp服務”,可實時查詢每個rtsp service連接的session數;
  8. 如需本地拉取的rtsp或rtmp流,點擊“預覽”;
  9. 如需停止,點擊“停止rtsp流”;

大牛直播SDK Demo展示

大牛直播SDK Demo頁面展示:

1. Windows RTMP直播推送SDK:

2. Windows轉發SDK:

3.Windows導播SDK:

4. Android RTMP直播推送SDK:

5. iOS RTMP直播推送:

6. Windows RTMP/RTSP直播播放SDK:

7. Android RTMP/RTSP直播播放SDK:

8. iOS RTMP/RTSP直播播放SDK:

9. Android播放、錄像、RTMP轉發-內置網關SDK(SmartRelayDemoV2)

音頻采集處理SDK

Windows音頻采集處理SDK

  1. 支持音頻源
  • ?支持Windows采集麥克風揚聲器和外部AAC, Speex WB, PCMA, PCMU數據接口輸入;
  1. 音頻合成
  • ?[音頻]支持揚聲器和麥克風音頻混音輸出(同時選擇“采集揚聲器”和“采集麥克風”);
  1. 音頻處理
  • ?支持音頻“端點檢測(VAD)”,自適應碼流,音頻碼流更節省;
  • ?支持回音消除功能;
  • ?支持噪音抑制功能;
  • ?支持自動增益控制。
  1. 對應Demo:
  • ?測試程序:SmartPublisherDemo.exe;
  • ?C++工程:WIN-PublisherSDK-CPP-Demo;
  • ?C#工程:WIN-PublisherSDK-CSharp-Demo。

視頻采集處理SDK

Windows視頻采集處理SDK

  1. 支持視頻源
  • ?支持Windows屏幕采集、屏幕裁剪特定窗口采集、攝像頭采集、擴展外部H.264數據對接;
  1. 攝像頭和屏幕合成
  • ?[攝像頭和屏幕實時切換]支持推送過程中,攝像頭和屏幕互相切換,單畫面顯示攝像頭或屏幕;
  • ?[攝像頭疊加到屏幕] 支持攝像頭按照設置坐標,疊加到屏幕指定位置,并支持實時關閉疊加層;
  • ?[屏幕疊加到攝像頭] 支持屏幕按照設定坐標,疊加到攝像頭指定位置,并支持實時關閉疊加層;
  1. 水印和透明度遮擋
  • ?[實時水印]支持動態水印設置,完美支持文字水印、實時時間水印和圖片水印
  • ?[透明度]可以設置透明度處理(設置遮蓋);
  1. 對應Demo:
  • ?測試程序:SmartPublisherDemo.exe;
  • ?C++工程:WIN-PublisherSDK-CPP-Demo;
  • ?C#工程:WIN-PublisherSDK-CSharp-Demo。

大牛直播互動SDK

目前,大牛直播SDK支持Windows/android一對一互動。

其中,windows需要在推送端,開啟回音消除功能,移動端,參考?SmartEchoCancellationV2 工程。

互動SDK
功能 功能描述
標準功能 支持推送端常規功能
支持播放端常規功能
回音消除 支持回音消除
降噪 支持環境音、手機干擾等引起的噪音降噪處理、自動增益、VAD檢測
污污直播app-污污直播破解版永久免费版