Web端H.265播放器研發解密

音視頻編解碼對于前端工程師是一個比較少涉足的領域,涉及到流媒體技術中的文本、圖形、圖像、音頻和視頻多種理論知識的學習,才能夠應用到具體實踐中,本團隊在多媒體領域深耕兩年多,才算是有一定產出,我們自研web播放器并支持h.265解碼,在碼率優化的大背景下(保持畫質不變情況下,應用圖像增強、roi區域檢測、智能場景分類和h265編解碼等多種技術能力,將碼流降低50%。達到減少帶寬成本,提升視頻服務QoE的目的),真正做到了h265解碼播放的全域覆蓋。

播放器整體架構

我們播放器整體架構設計如下:

本文主要分享了我們基于WebAssembly實現H.265格式的解封裝、解碼和播放。

背景

H.265又稱HEVC(全稱High Efficiency Video Coding,高效率視頻編碼),是ITU-T H.264/MPEG-4 AVC標準的繼任者。相比H.264,H.265擁有更高的壓縮率,也就意味著同樣碼率(又稱比特率是指每秒傳送的比特(bit)數。單位為bps(Bit Per Second),比特率越高,每秒傳送數據就越多,畫質就越清晰),H.265的畫質會更清晰,更高的壓縮率就能使用更低的存儲和傳輸成本。

  • 帶寬成本:在有限帶寬下H.265能傳輸更高質量的網絡視頻,理論上,H.265最高只需H.264編碼的一半帶寬即可傳輸相同質量視頻。更低的帶寬可以更好的降低存儲及傳輸成本,并為未來基于短視頻及直播領域更多更復雜好玩的互動玩法做鋪墊。
  • 轉碼成本:但是當前主流瀏覽器均不支持H.265原生視頻播放,因此通常視頻生產端需要針對瀏覽器做一次H.264視頻的轉碼來適配瀏覽器端如PC場景的播放,而增加了轉碼成本。如在淘寶直播中,假設以每天5萬場直播計算,每場直播轉碼成本20元,一天就是100萬的轉碼成本。
    為此,我們團隊對瀏覽器端H.265視頻播放的可行性及兼容性進行了一次探索,為移動端及PC端全量H.265做準備,也對瀏覽器端視音頻處理、WebAssembly實踐進行一次深入的嘗試。

H.264 vs H.265

H.264是當下用的最為廣泛的視頻編碼格式,H.265標準圍繞著現有的視頻編碼標準H.264,保留原來的某些技術,同時對一些相關的技術加以改進。新技術使用先進的技術用以改善碼流、編碼質量、延時和算法復雜度之間的關系,達到最優化設置。H.265和H.264都是基于塊的視頻編碼技術,主要的差別在于編碼單元的大小以及一些編碼算法細節,H.265將圖像劃分為“編碼樹單元(coding tree Unit, CTU)”,而不是像H.264那樣的16×16的宏塊。根據不同的編碼設置,編碼樹單元的尺寸可以被設置為64×64或有限的32×32或16×16。一般來說區塊尺寸越大,壓縮效率就越好。具體的算法及相關細節這里不具體展開了,還有一些其他的壓縮算法如因為H.265專利限制而生的開放編碼格式如AV1等,讀者可以參考其他相關文章。
h264vsh265.png

如下圖,可以看到同樣主觀畫面質量,H.265(500K)僅需H.264(800K)一半左右的帶寬碼率。
h264vsh265.png

瀏覽器現狀

如下圖,因為H.265專利及硬解支持情況不完善的原因,主流現代瀏覽器均不兼容H.265編碼的視頻播放(Edge新版本以插件方式支持),但是因為Apple對H.265的支持(這里作者認為這可能是一個很重要的標志,因為技術的發展很多時候不光是這個技術本身所決定的,而是很多因素共同作用的結果,商業也是其中很重要的一個因素),移動端ios safari在11.0版本以上支持原生播放。
h265comp

想要在瀏覽器端播放H.265視頻原生的<video />標簽沒有辦法支持,但是因為視頻格式本身是連續圖像畫面音頻的集合,參考了chromium的源碼及video標簽內部的實現原理,可以通過<canvas /> + Web Audio API 的結合來模擬實現一個虛擬的video標簽來實現播放器功能。

demo

因為直播流時效性的緣故,發布了一個播放H.265 mp4視頻(該視頻地址直接在瀏覽器中播放只有聲音而沒有畫面)的在線demo,讀者可以有一個直觀感受。
地址:https://g.alicdn.com/videox/mp4-h265/1.0.2/index.html
效果:
demo.gif

前期調研

視音頻基礎

因為前端領域對視頻領域的涉及場景不多,一個<video />標簽就可以滿足大部分場景,但是經歷了這幾年直播和短視頻的爆發,視頻的需求和功能也變得越來越復雜,開發之前閱讀了很多視音頻領域相關的書籍和文章,在此先對視音頻基礎進行一個簡單的介紹。

視頻中我們通常說的視頻的格式,比如 .mp4, .mov, .wmv, .m3u8, .flv 等等被稱為container。在一個視頻文件中音頻、視頻數據是分開存儲的,使用的壓縮算法也不一樣。其中container作為容器主要包含了video數據、audio數據、metadata(用于檢索視音頻payload格式等信息)。每個格式的封裝格式不一樣,比如FLV格式的基本單元是Tag,而MP4格式的基本單元是Box,輔助的meta信息用于檢索找到對應的原始數據。

而平時聽到的H.264, H.265等視頻編碼標準被稱為codec (COmpress and DECompress )。一個視頻格式比如mp4可以使用任何標準化的壓縮算法,這些信息都會被包含在一個視頻文件的meta信息中來告訴播放器該用什么編解碼算法來播放。

客戶端播放器

一個傳統的客戶端播放器播放一個視頻流經過了如下各個環節:

拉取數據 => 解封裝 => 音視頻解碼 => 采樣/像素數據發送到設備進行渲染。
client

對于流媒體,播放器客戶端通過拉流以數據源(音視頻流)為中心,進行管道式的傳輸。在此期間,對視頻流的讀取,轉換,分類,復制等一系列操作處理,以封裝的mp4流為例,需要對流進行解封裝、解碼、渲染等步驟:
stream

瀏覽器video標簽

在探究的過程中,為了了解主流瀏覽器不支持H.265視頻播放的原因,以及瀏覽器端實現播放器原理的了解,通過對Chromium瀏覽器官方文檔及video標簽實現源碼的閱讀,整理了一個流程圖。
chromium

可以看到瀏覽器內部對視頻流播放的實現,在經過了PipelineController等數據傳輸管道的處理后利用FFmpeg軟解或者Gpu硬解之后交給視頻設備及音頻設備進行同步及渲染。其中H.265的視頻因為硬解支持情況不完善,軟解可能有性能風險,所以在chrome中被關閉了不支持,在chromium中可以通過參數打開。我們就依照這個思路,利用瀏覽器提供的接口來實現一個模擬的video標簽。

設計過程

開發思路

開發思路按照從簡單到復雜的過程,對任務進行拆分,來完成H.265視頻點播及直播等各個場景的覆蓋,以mp4短視頻出發完成播放流程,再覆蓋直播場景,考慮如網絡抖動、內存控制等復雜因素,再針對直播m3u8等回放文件進行播放并開發視頻seek、倍速等功能。

mp4播放=>flv播放=>hls播放=>加入seek、倍速等功能

可行性分析

  • 思路:在最開始進行可行性分析時,參考結合了已有工具videoconverter.js和libde265.js對H.265視頻ffmpeg的編譯提取了hevc文件及mp3音頻文件在瀏覽器端進行了播放。
  • demo地址:https://sparkmorry.github.io/mse-learning/h265/
  • 表現:將720P的mp4視頻進行視頻和音頻的分離,通過 <canvas /> 繪制圖像,通過 <audio /> 標簽播放音頻,畫面在Macbook Pro上Chrome瀏覽器下在23fps左右。
  • 問題:

    • 不能達到解碼性能標準: 720P的視頻在Macbook Pro上僅在23fps左右,而原視頻是25fps,不能達到解碼性能標準,無法流暢播放。
    • 無法做到音畫同步: 該方案因為直接提取了hevc裸流文件,無法獲取視頻和音頻每幀的pts時間戳,無法做到嚴格的音畫同步。
  • 解決方案:

    • 性能:因為libde265.js是asm.js,通過對libde265.js開源庫的改造,打包WebAssembly測試性能情況
    • 音畫同步:參考flv.js、hls.js等開源視頻庫的方案,根據曾經的實踐經歷,js在解封裝方面的性能能夠完成視頻流文件解封裝,獲取每幀視頻、音頻播放的pts及原始數據交給解碼器進行解碼再渲染。
  • 方案調整:
    1

MP4點播流播放

  • 思路:根據上一過程調整的解決方案,通過js對mp4流進行解封裝,因為音頻解碼的復雜度不高,也先用js進行解碼,僅將視頻解碼模塊用已有的三方模塊libde265并替換為wasm解決性能問題,音視頻解碼模塊都自身維護一段緩存區,負責存儲解封裝模塊傳過來的packet數據,解決音畫同步的問題。
  • 表現:通過開源libde265實現的視頻解碼模塊,針對于720p的視頻流,平均解碼時間是45ms,不能滿足每一幀音頻播放時間間隔(40ms)。
  • 問題:視頻解碼性能仍然不夠。
  • 解決方案:

    • 丟幀:保證了音頻同步,丟掉部分非參考幀,但損失了部分體驗。所以提升解碼性能和改善播放策略才能有可能滿足當前方案的可行性。提升解碼性能和改善播放策略。
    • 提升解碼性能:用解碼性能更好的ffmpeg替換掉libde265。
    • 改善播放流程:因為每個requestAnimationFrame循環任務都是同步的,邊解碼邊播放。引入用WebWorker線程。通過改善視頻解碼模塊,解碼器內部開啟循環解碼,當外部的視頻播放設備需要播放下一幀時,直接從解碼器解碼完的幀緩存中讀取下一幀數據。實現了worker和主線程并行執行。
  • 方案調整:

    • demo地址:https://static-assets.cyt-rain.cn/h265/index.html
    • 設計流程
      2

FLV直播流播放

  • 思路:mp4視頻流暢播放,但在直播場景(如FLV視頻流)中,客戶端需要和服務端建立長鏈接,不斷接收流消息,借用FFmpeg本身對流媒體的支持,對視頻數據進行解封裝及解碼。
  • 表現:無法編譯FFmpeg網絡庫,TCP無法建立連接。
  • 問題:
    無法編譯FFmpeg網絡庫:TCP建立連接創建Socket時報錯,Emscripten工具無法編譯TCP連接相關配置

codec不支持:FLV官方協議不支持H.265。

  • 解決方案:

    • 無法編譯FFmpeg網絡庫:主線程利用fetch方法進行拉流,放到FFmpeg自定義緩沖區進行解封裝及解碼。因為直播流長時間播放需要不停的開辟、釋放內存空間,采用環形的數據緩沖區。
    • FLV官方協議不支持H.265:對FFmpeg及編碼端對H.265進行擴展,因為FFmpeg內部數據結構嵌套較深,替換js解封裝函數直接用FFmpeg的解封裝函數。
  • 方案調整:

    • 設計流程
      3

當前方案

播放流程

current

  1. 因為FFmpeg支持多種格式解封裝,只需要在在主線程中通過瀏覽器API(通常是fetch方法)拉取原始流數據并放到緩存中,等初始緩存到一個閾值時開啟Worker進行解封裝及解碼;
  2. 在子線程(Worker)中通過主線程fetch方法觸發的數據回調接收數據存入環形緩沖區(內存環)中;
  3. 子線程將讀取到的音頻幀輸送到主線程中,通過Web Audio API緩存音頻數據,根據已解碼的視頻幀緩存隊列循環解碼保證緩存中一直緩存10幀rgba圖像數據;
  4. 主線程中canvas根據音頻播放回調的pts消費并渲染視頻圖像;
  5. 循環以上操作直到fetch接口返回流已結束。

解碼器編譯

通過Emscripten工具可以把C語言編寫的FFmpeg庫編譯成wasm并在瀏覽器中應用到視音頻解碼中。
我們的視頻解碼場景和通常的播放器一樣,通過依賴FFmpeg的通用接口來實現解封裝和解碼的工作。先通過emscripten編譯ffmpeg庫,再通過靜態庫的方式依賴到解封裝和解碼入口程序中。
compile

測試表現

性能測試

測試視頻

因為flv直播視頻受時效性影響較大,拿720P高清的H.265 mp4視頻作為穩定輸入測試

  • 地址:https://gw.alicdn.com/bao/uploaded/LB1l2iXISzqK1RjSZFjXXblCFXa.mp4?file=LB1l2iXISzqK1RjSZFjXXblCFXa.mp4
  • 視頻參數:
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'https://gw.alicdn.com/bao/uploaded/LB1l2iXISzqK1RjSZFjXXblCFXa.mp4?file=LB1l2iXISzqK1RjSZFjXXblCFXa.mp4':Metadata:major_brand     : isomminor_version   : 512compatible_brands: isomiso2mp41encoder         : www.aliyun.com - Media TranscodingDuration: 00:01:00.10, start: 0.000000, bitrate: 907 kb/sStream #0:0(und): Video: hevc (Main) (hvc1 / 0x31637668), yuv420p(tv, bt709, progressive), 1280x720, 854 kb/s, 25 fps, 25 tbr, 12800 tbn, 25 tbc (default)Metadata:handler_name    : VideoHandlerStream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 48 kb/s (default)Metadata:handler_name    : SoundHandler

測試機器

  • lenovo ThinkPad T430

    • CPU: Intel(R) Core(TM) i5-3230M CPU@2.60GHz x64處理器
    • 內存: 8 GB
    • 系統: windows 10
  • MacBook Pro (Retina, 15-inch, Mid 2015)

    • CPU: 2.2 GHz Intel Core i7
    • 內存: 16 GB
    • 系統: macOS 10.14.2

性能情況

  • MBP下表現
decoder.wasm大小decoder.js大小平均每幀解碼時長內存占用cpu占用
1.4M168K26.79ms27M17~25%
  • 針對兩個pc筆記本進行了測試,平均每幀解碼(包含yuv420轉rgba)時長在各個瀏覽器的表現情況如下:
    注:此處Native(原生)表示針對mac系統原生編譯的FFmpeg作為依賴的解碼器(相對不考慮具體如x86、arm等計算機架構的WebAssembly的跨平臺方案而言)
設備ChromeSafariFireFoxEdgeNative
MacOS(i7)26.79ms22.19ms24.77ms-5.08ms
windows(i5)33.51ms-36.74ms86.72ms未測試

意味著最高能提供720P高清視頻如下幀率視頻流暢播放的能力:

設備ChromeSafariFireFoxEdge視頻基準Native
MacOS(i7)37fps45fps40fps-25fps196fps
windows(i5)30fps-27fps12fps25fps未測試

可以看到這兩臺機器中,在非高速運動等普通的如電商場景25fps幀率的高清720p視頻已經能達到生產環境的標準,但是距離原生的速度還有一定距離。

瀏覽器兼容性

主要用到了WebAssembly及WebWorker的支持,實際測試中主流瀏覽器Chrome、Safari、Firefox、Edge均能通過兼容性測試。

  • WebAssembly
    wasm
  • WebWorker
    worker

TODO

當前的技術方案已經能在大部分機器的主流瀏覽器上流暢的播放720P的高清直播流,但是在Edge瀏覽器及性能稍差的機器上還是存在高清視頻解碼性能不能滿足流暢播放的風險,針對WebAssembly達到native速度的目標還有一定距離,尤其是匯編并行計算的支持,在視音頻及大規模數據處理中是很常見的性能優化策略,作者整理了幾個優化的方向,在未來還有更多探索的空間:

  • 匯編
    FFmpeg中解碼有較多利用匯編進行并行計算的優化,但是匯編指令是cpu specific的(比如x86指令和arm指令),而wasm是跨平臺的基于棧的虛擬機。Emscripten不支持匯編的編譯,考慮用clang等llvm前端將FFmpeg的.c和匯編.asm文件編譯成LLVM IR(LLVM Intermediate Representation),然后通過fastcomp或者其他后端來編譯測試。
  • 硬解
    FFmpeg3.3以上開始支持自動硬解探測,支持的硬件設備根據不同操作系統及硬件會有不同的支持,具體參考:https://trac.ffmpeg.org/wiki/HWAccelIntro 。因為wasm是跨平臺的虛擬指令集,支持程度還要待進一步探究。
  • 多線程
    FFmpeg內部解碼有多線程來提高解碼性能,通過pthread可以支持跨平臺的多線程支持的,但是如果不支持共享內存,則線程之間的數據傳輸會有很多性能消耗(深拷貝或者Transfered Object)。瀏覽器端共享內存通過SharedArrayBuffer來實現,因為有安全隱患,大部分主流瀏覽器關閉了SharedArrayBuffer、Chrome67+開始恢復。考慮到兼容性多線程的支持還要再進行嘗試。
  • WebGL渲染
    解碼平均時長中有4ms左右(15%)在yuv轉rgba上,通過WebGL可以用gpu加速圖像的計算,但是同時與WebGL的數據交換又會產生一定的性能損耗,需要再測試查看性能結果

未來展望

通過H.265視頻播放將開源視音頻庫FFmpeg的能力及WebAssembly性能的優勢在瀏覽器端視音頻處理上有了一次深入的嘗試。視頻作為一種多媒體形式,相比現有的文字、圖像、音頻都能有更生動及更豐富信息的表現。尤其經過了直播和短視頻的爆發增長后,成為了一種基礎的多媒體形式,也是網絡及移動端手機性能等技術發展的體現。未來隨著5G及更高性能的硬件設備的發展會被更廣泛的應用到各個領域。瀏覽器在這場視頻革命中也是不可或缺的一個環節,通過這次的探索,為未來瀏覽器端擴展視音頻處理的通用能力提供了想象的空間,同時也在瀏覽器端通過WebAssembly向native性能及能力靠近的路上做了一個落地的嘗試,雖然從測試情況看現在的表現還不如native,但是隨著標準及技術的演進,為未來對性能要求比較高的圖形圖像及人工智能等相關方向在瀏覽器端處理一定會漸漸被廣泛的應用起來,比如如下幾個方向:

  • 擴展瀏覽器端視頻播放能力
    借助FFmpeg強大的編解碼能力,除了H.265視頻的播放,未來還可以在瀏覽器端兼容各種格式及編碼類型的視頻播放。如不同的編碼格式AV1、不同的容器格式mov格式等等。
  • 擴展瀏覽器端視音頻處理能力
    借助FFmpeg及其他語言框架的現有能力,還可以在視音頻領域做更多復雜的操作如視頻濾鏡、視頻剪切、視頻格式轉換等功能,減少網絡傳輸及存儲的成本。
  • 基于WebAssembly的高性能web應用
    借助WebAssembly的跨平臺優勢,可以將傳統的其他語言的開源框架如圖形相關開源庫OpenGL、SDL等的能力移植到瀏覽器上來。借助性能上的優勢也可以將傳統的圖像、3D等運算能力要求較高的應用擴展到瀏覽器端。

參考

  • Chromium媒體元素源碼: https://github.com/chromium/chromium/tree/master/media
  • WebAssembly: https://webassembly.org/
  • 優秀的開源視音頻處理框架FFmpeg: https://www.ffmpeg.org/
  • 基于LLVM編譯的WebAssembly打包工具集Emscripten:https://emscripten.org/index.html
  • 基于WebAssembly的ogg播放器:https://github.com/brion/ogv.js
  • 基于FFmpeg的簡單播放器:https://github.com/leixiaohua1020/simplest_ffmpeg_player

后言

本文介紹了我們在Web端H.265播放器上研發的過程和進展,后續還有很多繼續優化和深入的點。對相關知識感興趣的同學歡迎溝通交流,附上我們前端團隊的介紹:

淘寶技術部內容與開放平臺前端團隊是淘系核心的商業變革陣地,相對于橫向資源前端團隊,我們更深入在內容電商、音視頻技術領域,探尋創新商業模式及業界領先技術。

本團隊目前正火熱招聘20屆優秀畢業生,歡迎有志之士加入!
img

或者直接聯系團隊負責人: 靈玉 lingyu.csh@taobao.com

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/536647.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/536647.shtml
英文地址,請注明出處:http://en.pswp.cn/news/536647.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

拳擊 武術java父類,拳擊是一種很有力量的武術類型

原標題&#xff1a;拳擊是一種很有力量的武術類型拳擊是一種很有力量的武術類型&#xff0c;拳擊比賽策略有很多&#xff0c;圍繩技術是其中之一。那么拳擊比賽策略技巧有哪些呢&#xff1f;下面養生之道網為您解析拳擊比賽策略技巧有哪些&#xff0c;看看吧。1、當拳手靠在圍繩…

捧上天的AI落地困難,“ 不懂變通”的華為云如何應付?

前幾年&#xff0c;AI幾乎被捧上天&#xff0c;各大公司傾巢出動&#xff0c;推出了不少吸眼球的應用和產品。如今&#xff0c;這些AI成果是否真得讓企業從中獲得價值&#xff1f;繞不開的數據、隱私和安全問題作何解&#xff1f;不同領域、不同規模、不同技術能力的企業如何最…

Apache-Flink深度解析-DataStream-Connectors之Kafka

Kafka 簡介Apache Kafka是一個分布式發布-訂閱消息傳遞系統。 它最初由LinkedIn公司開發&#xff0c;LinkedIn于2010年貢獻給了Apache基金會并成為頂級開源項目。Kafka用于構建實時數據管道和流式應用程序。它具有水平擴展性、容錯性、極快的速度&#xff0c;目前也得到了廣泛的…

Java使用繼承的語法是,Java基礎語法八 繼承

1、超類和子類超類和子類父類與子類多態&#xff1a;一個對象變量可以指示多種實際類型的現象稱為多態一個變量可以引用父類對象&#xff0c;也可以引用其子類對象&#xff0c;這就是多態。不能將一個超類的引用賦給子類變量&#xff0c;因為調用子類方法時可能發生運行錯誤子類…

kaka 1.0.0 重磅發布,服務于后端的事件領域模型框架。

百度智能云 云生態狂歡季 熱門云產品1折起>>> kaka 1.0.0正式發布了&#xff0c;從三個月前的kaka-notice-lib 1.0.0的發布&#xff0c;經過多次研磨&#xff0c;終于迎來了本次重大更新。 kaka是一款服務于java后端的事件領域模型框架&#xff0c;主要目的為解耦業…

java配置文件工具類,java項目加載配置文件的工具類

java項目加載配置文件的工具類package com.loadproperties;import java.io.IOException;import java.io.InputStream;import java.util.Properties;public class ConfigUtil {private static InputStream input;private volatile Properties configuration new Properties();/…

如何把WAV格式音頻轉換為MP3格式

WAV為微軟公司&#xff08;Microsoft)開發的一種聲音文件格式&#xff0c;它符合RIFF(Resource Interchange File Format)文件規范&#xff0c;用于保存Windows平臺的音頻信息資源&#xff0c;被Windows平臺及其應用程序所廣泛支持&#xff0c;因此在聲音文件質量和CD相差無幾&…

php 異步處理類,php異步處理類

該類可以請求HTTP和HTTPS協議&#xff0c;還可以處理301、302重定向以及GZIP壓縮等。[PHP]代碼//使用方法require(asynHandle.class.php);$obj new asynHandle();$result $obj->Request(http://baidu.com);$result2 $obj->Get(https://mail.google.com/);echo "{…

惡意軟件盯上了加密貨幣,兩家以色列公司受到攻擊

近日&#xff0c;網絡安全公司Palo Alto Networks威脅研究部門Unit 42發博稱&#xff0c;已確認Cardinal RAT自2017年4月起對兩家從事外匯和加密交易軟件開發的以色列金融科技公司發起過攻擊。 Cardinal RAT是可遠程訪問特洛伊木馬&#xff08;RAT&#xff09;&#xff0c;攻擊…

php 自定義打印模板下載,PHP – 創建自定義模板系統?

我已經在這里搜索過,令人驚訝的是我找不到答案.我發現了一個類似的線程,但沒有真正的解決方案.復雜的部分是循環,如果我不需要循環我可以只是做一個常規替換.所以,我有一個帶有一些標記的.html文件,如下所示&#xff1a;{{startloop}}{{imgname}}{{endLoop}}我想要做的是用其他…

騰訊財報中“最大秘密”:2018云收入91億元,交首份TO B答卷

騰訊財報中“最大秘密”云業務收入又一次被公開了&#xff1a;2018年&#xff0c;騰訊云收入91億元&#xff0c;增長100%。 3月21日&#xff0c;騰訊發布2018年Q4及全年財報&#xff0c;2018全年收入3126.94億元同比增長32%&#xff0c;凈利潤(Non-GAAP)774.69億元。而被列進“…

根據坐標如何在matlab中l連成曲線,matlab中,如何將兩條曲線畫在一個坐標系里,plot(x1,x2,y1,y2)還是怎樣...

matlab中&#xff0c;如何將兩條曲線畫在一個坐標系里&#xff0c;plot(x1,x2,y1,y2)還是怎樣以下文字資料是由(歷史新知網www.lishixinzhi.com)小編為大家搜集整理后發布的內容&#xff0c;讓我們趕快一起來看一下吧&#xff01;matlab中&#xff0c;如何將兩條曲線畫在一個坐…

Android 物聯網 傳感器

前幾天做了一個嵌入式課設。將傳感器收集到的數據傳到手機制作的APP里。 項目中涉及到的主要的java代碼和xml布局文件上傳到了github&#xff0c;https://github.com/123JACK123jack/Android轉載于:https://www.cnblogs.com/libin123/p/10578601.html

java已被弱化簽名,高效Java第四十條建議:謹慎設計方法簽名

作用有助于設計易于學習和使用的API。如何做——謹慎地選擇方法的名稱1.選擇易于理解的&#xff0c;并且與同一個包中的其他名稱風格一致的名稱。2.選擇與大眾認可的名稱相一致的名稱。如何做——不要過于追求提供便利的方法每個方法都應該盡其所能。方法太多會使類難以學習、使…

curl有php內存緩存,PHP CURL內存泄露的解決方法

PHP CURL內存泄露的解決方法curl配置平淡無奇&#xff0c;長時間運行發現一個嚴重問題&#xff0c;內存泄露&#xff01;不論用單線程和多線程都無法避免&#xff01;是curl訪問https站點的時候有bug&#xff01;內存泄露可以通過linux的top命令發現&#xff0c;使用php函數mem…

MySQL學習【第五篇SQL語句上】

一.mysql命令 1.連接服務端命令 1.mysql -uroot -p123 -h127.0.0.1 2.mysql -uroot -p123 -S /tmp/mysql.sock 3.mysql -uroot -p123 -hlocalhost 4.mysql -uroot -p123 2.mysql登陸后的一些命令 1.\h或者help   查看幫助 2.\G       格式化查看數據&#xff08;以k…

phpexcel.php linux,phpexcel在linux系統報錯如何解決

最近有個tp3.2的項目遷移到linux系統上了&#xff0c;突然有天發現原本在win server 2008上運行沒問題的excel導出功能在新的系統上不能使用了。報錯如下&#xff1a;說是1762行有問題&#xff0c;找到這個文件的代碼看看&#xff1a;/*** Get an instance of this class** acc…

優雅的redux異步中間件 redux-effect

不吹不黑&#xff0c;redux蠻好用。只是有時略顯繁瑣&#xff0c;叫我定義每一個action、action type、使用時還要在組件上綁定一遍&#xff0c;臣妾做不到呀&#xff01;下面分享一種個人比較傾向的極簡寫法&#xff0c;仍有待完善&#xff0c;望討論。 github: github.com/li…

oracle 中累加函數,Oracle 分析函數分組累加!

用戶號碼 登陸時間13000000002010-01-0113000000012010-01-0113000000022010-01-0213000000012010-01-0213000000032010-01-0313000000022010-01-0313000000042010-01-0413000000032010-01-0413000000042010-01-0213000000062011-01-0413000000012011-01-04剔除重復登陸的用戶,…

asp.net core系列 48 Identity 身份模型自定義

一.概述 ASP.NET Core Identity提供了一個框架&#xff0c;用于管理和存儲在 ASP.NET Core 應用中的用戶帳戶。 Identity添加到項目時單個用戶帳戶選擇作為身份驗證機制。 默認情況下&#xff0c;Identity可以使用的 Entity Framework (EF) Core 數據模型。 本文介紹如何自定義…