<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 我們如何在 Mail.Ru Cloud 中實現視頻播放器 > 原文: [http://highscalability.com/blog/2016/3/28/how-we-implemented-the-video-player-in-mailru-cloud.html](http://highscalability.com/blog/2016/3/28/how-we-implemented-the-video-player-in-mailru-cloud.html) ![](https://img.kancloud.cn/8f/a6/8fa614a6af6cf728041ee165b6cc9f51_225x105.png) 我們最近在 [Mail.Ru Cloud](https://cloud.mail.ru/) 中添加了視頻流服務。 開發首先考慮將新功能用作通用的“瑞士軍刀”,它將播放任何格式的文件并可以在具有可用云的任何設備上工作。 上傳到云端的視頻內容大體上屬于兩類之一:“電影/系列”和“用戶視頻”。 后者是用戶使用手機和相機拍攝的視頻,就格式和編解碼器而言,這些視頻用途最為廣泛。 由于許多原因,在沒有事先進行標準化的情況下在其他最終用戶設備上觀看這些視頻通常是一個問題:缺少必需的編解碼器,或者文件太大而無法下載,等等。 在本文中,我將詳細介紹如何在 Mail.Ru Cloud 中播放視頻,以及如何使 Cloud Player“雜食化”并確保對最大數量的最終用戶設備的支持 。 ## 存儲和緩存:兩種方法 上傳后,許多服務(例如 YouTube,社交網絡等)會將用戶的視頻轉換為適當的格式。 視頻只有在轉換后才能播放。 Mail.Ru Cloud 中使用了另一種方法:**原始文件在播放時會進行轉換**。 與某些專門的視頻托管網站不同,我們無法更改原始文件。 我們為什么選擇此選項? Mail.Ru Cloud 主要是一種云存儲,如果用戶在下載文件時發現文件質量下降或文件大小發生了一些變化,他們將感到非常驚訝。 另一方面,我們無法承受**存儲所有文件的預先轉換后的副本:這將需要太多空間**。 我們還必須做很多額外的工作,因為某些存儲的文件將永遠不會被監視,甚至一次也不會被監視。 快速轉換的另一個優點是:如果我們決定更改轉換設置或例如添加其他功能,則無需重新轉換舊視頻(并非總是如此) 可能,因為原始視頻已經消失了)。 在這種情況下,一切都會自動應用。 ## 這個怎么運作 我們正在使用 Apple 創建的 HLS(HTTP 實時流)格式[進行在線視頻流。 HLS 的思想是將每個視頻文件都切成小片段(稱為“媒體片段文件”),這些片段會添加到播放列表中,并為每個片段指定名稱和時間(以秒為單位)。 例如,將一個兩小時的電影切成十秒鐘的片段,作為一系列 720 個媒體片段文件。 根據用戶希望從哪一刻開始觀看視頻,播放器會從傳輸的播放列表中請求適當的片段。 **HLS** 的好處之一是**用戶無需在播放器讀取文件頭時等待視頻開始播放**(等待時間可能會很長) 如果是完整版電影且移動互聯網速度較慢)。](https://developer.apple.com/streaming/) 這種格式提供的另一個重要可能性是**自適應流**,它允許根據用戶的 Internet 速度即時更改質量。 例如,您開始使用 3G 以 360p 觀看,但是火車駛入 LTE 區域后,您將繼續以 720p 或 1080p 觀看。 它在 HLS 中非常簡單地實現:播放器會獲得“主播放列表”,其中包括針對不同帶寬的備用播放列表。 加載片段后,播放器會評估當前速度,并據此決定下一個片段的質量:相同,較低或較高。 我們目前支持 240p,360p,480p,720p 和 1080p。 ## 后端 , [![](https://img.kancloud.cn/13/aa/13aa2b86dbce3ee185166b59ae3b0c67_600x283.png) ](https://habrastorage.org/files/1c6/c3e/67d/1c6c3e67dd6c4b0bbe4c2595aeffd099.png) Mail.Ru 云服務由**三組服務器**組成。 第一組是**應用程序服務器**,它接受視頻流請求:它創建一個 HLS 播放列表并將其發送回去,分發轉換后的片段,并設置轉換任務。 第二組是具有嵌入式邏輯的**數據庫( [Tarantool](http://tarantool.org/) ),用于存儲視頻信息并管理轉換隊列。 第三組**轉換器**從 Tarantool 中的隊列接收任務,然后將任務完成情況再次記錄在數據庫中。 收到視頻文件片段的請求后,我們首先在我們的一臺服務器上檢查數據庫,以獲取轉換后的質量要求的即用型片段。 這里有兩種情況。** 第一種情況:我們確實有一個轉換后的片段。 在這種情況下,我們會立即將其寄回。 如果您或其他人最近提出了要求,則該片段將已經存在。 這是第一個緩存級別,適用于所有轉換的文件。 值得一提的是,我們還使用了另一種緩存級別,其中經常請求的文件分布在多個服務器上,以避免網絡接口過載。 第二種情況:我們沒有轉換后的片段。 在這種情況下,將在數據庫中創建一個轉換任務,我們等待它完成。 正如我們之前所說,它是 Tarantool(一個非常快速的開源 NoSQL 數據庫,可讓您在 Lua 中編寫存儲過程),它負責存儲視頻信息和管理轉換隊列。 應用程序服務器和數據庫之間的通信如下進行。 應用服務器發出一個請求:“我需要 720p 質量的 movie.mp4 文件的第二個片段; 準備等待的時間不超過 4 秒鐘”,并且在 4 秒鐘之內它將收到有關從何處獲取片段的信息或錯誤消息。 因此,數據庫客戶端對立即執行任務或通過一系列復雜的操作不感興趣如何執行任務:它使用非常簡單的界面,可以發出請求并接收所請求的內容。 我們提供數據庫容錯能力的方法是**主副本故障轉移**。 數據庫客戶端僅將請求發送到主服務器。 如果當前的主服務器有問題,我們會將其中一個副本標記為主服務器,然后將客戶端重定向到新的主服務器。 當客戶端繼續與主機交互時,這樣的主副本切換對客戶端是透明的。 除了應用程序服務器之外,還有誰可以充當數據庫客戶端? 可能是那些準備開始轉換片段的轉換器服務器,現在需要到源視頻文件的參數化 HTTP 鏈接。 這種轉換器和 Tarantool 之間的通信類似于上述應用服務器的接口。 轉換程序發出一個請求:“給我一個任務,我準備等待 10 秒鐘”,如果任務在這 10 秒鐘內出現,則將任務交給正在等待的轉換程序之一。 我們在 Tarantool 內部的 Lua 中使用了 IPC 通道,以輕松實現客戶端到轉換器的任務轉發。 通道允許不同請求之間的通信。 這是一些用于轉換片段的簡化代碼: ``` function get_part(file_hash, part_number, quality, timeout) -- Trying to select the requested fragment local t = v.fragments_space.index.main:select(file_hash, part_number, quality) -- If it exists — returning immediately if t ~= nil then return t end -- Creating a key to identify the requested fragment, and an ipc channel, then writing it -- in a table in order to receive a “task completed” notification later local table_key = msgpack.encode{file_hash, part_number, quality} local ch = fiber.channel(1) v.ctable[table_key] = ch -- Creating a record about the fragment with the status “want to be converted” v.fragments_space:insert(file_hash, part_number, quality, STATUS_QUEUED) -- If we have idle workers, let’s notify them about the new task if s.waitch:has_readers() then s.waitch:put(true, 0) end -- Waiting for task completion for no more than “timeout” seconds local body = ch:get(timeout) if body ~= nil then if body == false then -- Couldn’t complete the task — return error return box.tuple.new{RET_ERROR} else -- Task completed, selecting and returning the result return v.fragments_space.index.main:select{file_hash, part_number, quality} end else -- Timeout error is returned return box.tuple.new{RET_ERROR} end end local table_key = msgpack.encode{file_hash, part_number, quality} v.ctable[table_key]:put(true, 0) ``` 實際的代碼稍微復雜一點:例如,它考慮了在請求時片段處于“正在轉換”狀態的場景。 由于采用了這種方案,轉換器可以立即收到新任務的通知,而客戶端也可以立即收到任務的完成的通知。 這非常重要,因為用戶看到視頻加載微調器的時間越長,他們甚至有可能在視頻開始播放之前就離開頁面。 如下圖所示,大多數轉化,因此等待時間不會超過幾秒鐘。 ![](https://img.kancloud.cn/64/74/6474091076d924956cd6dccd490c9af5_600x343.png) ## 轉換次數 對于**轉換**,我們使用的是根據需要修改的 **FFmpeg** 。 我們最初的計劃是使用 FFmpeg 內置工具進行 HLS 轉換。 但是,我們的用例遇到了問題。 如果您要求 FFmpeg 將 20 秒的文件轉換為具有 10 秒的片段的 HLS,則會得到兩個文件和一個播放列表,它們可以毫無問題地播放。 但是,如果您要求先轉換 0 至 10 秒,然后再轉換 10 至 20 秒(啟動 FFmpeg 轉換器的另一個實例),則從一個文件轉換為另一個文件時(大約在 10 秒),您會聽到明顯的喀噠聲。 我們花了幾天時間嘗試不同的 FFmpeg 設置,但沒有成功。 因此,我們必須進入 FFmpeg 并編寫一個小補丁。 它需要一個命令行參數來解決“ click”錯誤,該錯誤源于對音頻和視頻軌道進行編碼的細微差別。 此外,我們還使用了當時尚未包含在 FFmpeg 上游的其他一些可用補丁。 例如,一個[補丁](https://trac.ffmpeg.org/ticket/2513),用于解決 MOV 文件轉換緩慢的已知問題(由 iPhone 制作的視頻)。 一個名為“ Aurora” 的**守護程序控制從數據庫獲取任務并啟動 FFmpeg 的過程。 “ Aurora”守護程序以及位于數據庫另一端的守護程序都是用 Perl 編寫的,并且與 EV 事件循環和各種有用的模塊異步工作,例如: [EV-Tarantool](https://github.com/Mons/EV-Tarantool) 和 [Async :: Chain](https://metacpan.org/pod/Async::Chain) 。** 有趣的是,**沒有為 Mail.Ru Cloud 中的新視頻流服務**安裝額外的服務器:轉換(需要大量資源的部分)在特別隔離的環境中在我們的存儲上運行。 日志和圖形顯示,我們的能力所能承受的負載是我們現在所能承受的幾倍。 僅供參考:自我們的視頻流媒體服務于 2015 年 6 月啟動以來,已請求 **500 萬以上的獨特視頻; 每分鐘觀看 500–600 個唯一文件**。 ## 前端 如今,幾乎每個人都擁有智能手機。 或兩個。 為您的朋友和家人制作簡短的視頻沒什么大不了的。 這就是為什么我們準備好有人將視頻從手機或平板電腦上傳到 Mail.Ru Cloud 并立即從其設備中刪除視頻以釋放空間的情況。 如果用戶想向他人展示此視頻,則只需使用 Mail.Ru Cloud 應用程序將其打開,或在其桌面上的 Cloud Web 版本中啟動播放器。 現在可以不在手機上存儲所有視頻片段,同時始終可以在任何設備上訪問它們。 移動互聯網上的流式傳輸比特率降低了,因此,以兆字節為單位的大小也降低了。 此外,在移動平臺上播放視頻時,我們使用 Android 和 iOS 本機庫。 這就是為什么視頻可以在移動瀏覽器中“開箱即用”的智能手機和平板電腦上播放的原因:我們無需為使用的格式創建額外的播放器。 與網絡版本相似,在臺式計算機上,自適應流機制被激活,并且圖像質量動態適應當前帶寬。 我們的播放器與競爭對手的播放器之間的主要區別之一是我們的視頻播放器獨立于用戶的環境。 在大多數情況下,開發人員會創建兩個不同的播放器:一個是帶有 Flash 界面的播放器,另一個是(具有本地 HLS 支持的瀏覽器,例如 Safari),一個是完全相同的,但是用 HTML5 實現,隨后上傳了適當的文件。 接口。 我們只有一名球員。 我們的目標是可以輕松更改界面。 因此,我們的播放器在視頻和音頻方面看起來都非常相似-所有圖標,布局等均以 HTML5 編寫。 播放器不依賴于播放視頻所使用的技術。 我們使用 Flash 繪制視頻,但是整個界面都基于 HTML; 因此,我們不會遇到版本同步問題,因為不需要支持特定的 Flash 版本。 一個開放源代碼庫足以播放 HLS。 我們編寫了一個墊片,將 HTML5 視頻元素界面轉換為 Flash。 這就是為什么我們可以假設我們將始終使用 HTML5 來編寫整個界面的原因。 如果瀏覽器不支持這種格式,我們只需將本地視頻元素替換為自己的實現相同界面的元素。 如果用戶的設備不支持 Flash,則視頻將以具有 HLS 支持的 HTML5 播放(到目前為止,僅在 Safari 中實現)。 使用本地工具在 Android 4.2+和 iOS 上播放 HLS。 如果沒有支持且沒有本機格式,我們將為用戶提供文件下載。 ## *** 如果您有實現視頻播放器的經驗,歡迎訪問評論部分:我非常想知道如何將視頻分成多個片段,如何在存儲和緩存之間進行選擇,以及面臨的其他挑戰。 總之,讓我們分享我們的經驗。 [關于 HackerNews](https://news.ycombinator.com/item?id=11375147) 很棒的文章! 很棒的文章。 您能告訴我們更多有關 ffmpeg 補丁以消除音頻點擊的信息嗎? 謝謝。 如此棒的文章。 因此,轉換的視頻(頻繁和較少)在 ttl 之后會自動刪除嗎? 其次,為什么轉換器使用 http 協議從存儲中獲取視頻? 使用套接字不能更快完成嗎? 您啟動了多少個 tarantool 實例? TT 集群有多大? 對于此特定任務,我們只有兩個實例-主實例和副本實例。 我們知道,在 Mail.Ru 集團的在線廣告系統上,生產中的 Tarantool 集群的最大規模約為 500 個實例。 For this specific task we only have two instances - a master and a replica. The maximum knows to us size of a Tarantool cluster at production is around 500 instances at the Mail.Ru Group's online ad system.
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看