โปรโตคอลการสตรีมของ Web Receiver

Web Receiver SDK รองรับโปรโตคอล สตรีมมิง 3 ประเภทในปัจจุบัน ได้แก่

DASH, HTTP Live Streaming และ Smooth Streaming

ในเอกสารนี้ เราจะแสดงรายการการสนับสนุนของเราสำหรับโปรโตคอลสตรีมมิงแต่ละแบบ โปรดทราบว่าคำอธิบายแท็กที่รองรับสำหรับแต่ละโปรโตคอลนั้นค่อนข้างสั้น เมื่อเทียบกับข้อมูลจำเพาะของโปรโตคอลโดยละเอียด เป้าหมายคือการสรุปและทําความเข้าใจวิธีใช้แต่ละโปรโตคอลอย่างคร่าวๆ และทราบถึงฟีเจอร์ของโปรโตคอลที่รองรับในอุปกรณ์ที่พร้อมใช้งาน Cast เพื่อมอบประสบการณ์การสตรีม

การสตรีมที่ปรับเปลี่ยนได้แบบไดนามิกผ่าน HTTP (DASH)

ข้อกำหนดโดยละเอียดสำหรับ DASH ของ ISO

DASH คือโปรโตคอลสตรีมมิงแบบอัตราบิตที่ปรับเปลี่ยนได้ซึ่งช่วยให้สตรีมวิดีโอคุณภาพสูงผ่านเซิร์ฟเวอร์ HTTP(S) ได้ ไฟล์ Manifest แบบ XML ประกอบด้วยข้อมูลเมตาส่วนใหญ่สำหรับวิธีเริ่มต้นและดาวน์โหลดเนื้อหาวิดีโอ แนวคิดหลักที่ Web Receiver Player รองรับคือ <Period>, <AdaptationSet>, <Representation>, <SegmentTemplate>, <SegmentList>, <BaseUrl> และ <ContentProtection>

ไฟล์ Manifest สำหรับ DASH จะเริ่มต้นด้วยแท็กรูท <MPD> และภายในจะมีแท็ก <Period> อย่างน้อย 1 แท็ก ซึ่งแสดงเนื้อหาสตรีมมิง 1 รายการ แท็ก <Period> ช่วยให้เรียงลำดับเนื้อหาสตรีมมิงส่วนต่างๆ ได้และมักใช้เพื่อแยกเนื้อหาหลักและโฆษณา หรือเนื้อหาวิดีโอหลายรายการที่ต่อเนื่องกัน

<AdaptationSet> ภายใต้ <MPD> คือชุดการนำเสนอสำหรับสตรีมสื่อประเภทหนึ่ง ซึ่งโดยมากเป็นวิดีโอ เสียง หรือคำบรรยาย Mimetype ที่มีการรองรับมากที่สุดคือ "video/mp4", "audio/mp4" และ "text/vtt" คุณอาจรวม <ContentComponent contentType="$TYPE$"> (ไม่บังคับ) ไว้ในชื่อ <AdaptationSet> ได้

ภายใน <AdaptationSet> แต่ละรายการ จะมีรายการแท็ก <Representation> รายการอยู่ และ Web Receiver Player จะใช้ข้อมูล codecs เพื่อเริ่มต้นบัฟเฟอร์ต้นทาง MSE และข้อมูล bandwidth เพื่อเลือกการแสดง/อัตราบิตที่เหมาะสมที่จะเล่นโดยอัตโนมัติ

สำหรับ <Representation> แต่ละรายการ กลุ่มสื่อจะอธิบายโดยใช้ <BaseURL> สำหรับการแสดงกลุ่มเดี่ยว <SegmentList> สำหรับรายชื่อกลุ่ม (คล้ายกับ HLS) หรือ <SegmentTemplate>

สำหรับ <SegmentTemplate> จะบ่งบอกลักษณะการแสดงกลุ่มการเริ่มต้นและกลุ่มสื่อผ่านการกำหนดเทมเพลต ในตัวอย่างด้านล่าง $Number$ ระบุหมายเลขกลุ่มเป็นพร้อมใช้งานจาก CDN จากนั้น ระบบจะแปล เป็น seg1.m4s, seg2.m4s ฯลฯ เมื่อเล่นไปเรื่อยๆ

<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:ns2="http://www.w3.org/1999/xlink"
  profiles="urn:mpeg:dash:profile:isoff-live:2011,http://dashif.org/guidelines/dash264" type="static"
  publishTime="2016-10-05T22:07:14.859Z" mediaPresentationDuration="P1DT0H0M0.000S" minBufferTime="P0DT0H0M7.500S">
  <Period id="P0">
    <AdaptationSet lang="en" segmentAlignment="true">
      <ContentComponent id="1" contentType="audio"/>
      <SegmentTemplate media="seg$Number$.m4s" initialization="seginit.mp4"
        duration="10000" startNumber="1" timescale="1000" presentationTimeOffset="0"/>
      <Representation id="1" bandwidth="150123" audioSamplingRate="44100"
        mimeType="audio/mp4" codecs="mp4a.40.2" startWithSAP="1">
        <AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
        <BaseURL>http://www.google.com/testVideo</BaseURL>
      </Representation>
    </AdaptationSet>
    <AdaptationSet segmentAlignment="true">
      <ContentComponent id="1" contentType="video"/>
      <SegmentTemplate media="seg$Number$.m4s" initialization="seginit.mp4"
        duration="10000" startNumber="1" timescale="1000" presentationTimeOffset="0"/>
      <Representation id="1" bandwidth="212191" width="384" height="208" sar="26:27"
        frameRate="25" mimeType="video/mp4" codecs="avc1.42c01f" startWithSAP="1">
        <BaseURL>http://www.google.com/testVideo/bitrate1/</BaseURL>
      </Representation>
      <Representation id="1" bandwidth="366954" width="512" height="288" sar="1:1"
        frameRate="25" mimeType="video/mp4" codecs="avc1.42c01f" startWithSAP="1">
        <BaseURL>http://www.google.com/testVideo/bitrate2/</BaseURL>
      </Representation>
      <Representation id="1" bandwidth="673914" width="640" height="352" sar="44:45"
        frameRate="25" mimeType="video/mp4" codecs="avc1.42c01f" startWithSAP="1">
        <BaseURL>http://www.google.com/testVideo/bitrate3/</BaseURL>
      </Representation>
    </AdaptationSet>
  </Period>
</MPD>

ใน <SegmentTemplate> เป็นเรื่องปกติที่จะใช้แท็ก <SegmentTimeline> เพื่อระบุความยาวของแต่ละส่วนและกลุ่มที่ทำซ้ำ timescale (หน่วยที่ใช้แทน 1 วินาที) มักจะรวมอยู่ในแอตทริบิวต์ของ <SegmentTemplate> เพื่อให้เราสามารถคำนวณเวลาของเซกเมนต์โดยอิงตามหน่วยนี้ได้ ในตัวอย่างด้านล่าง แท็ก <S> หมายถึงแท็กกลุ่ม แอตทริบิวต์ d จะระบุความยาวของกลุ่ม และแอตทริบิวต์ r จะระบุจำนวนส่วนที่มีระยะเวลาเดียวกันซ้ำเพื่อให้ $Time$ คำนวณได้อย่างถูกต้องสำหรับการดาวน์โหลดกลุ่มสื่อตามที่ระบุไว้ในแอตทริบิวต์ media

<SegmentTemplate>
  timescale="48000"
  initialization="$RepresentationID$-init.dash"
  media="$RepresentationID$-$Time$.dash"
    startNumber="1">
    <SegmentTimeline>
      <S t="0" d="96256" r="2" />
      <S d="95232" />
      <S d="96256" r="2" />
      <S d="95232" />
      <S d="96256" r="2" />
   </SegmentTimeline>
</SegmentTemplate>

สำหรับตัวแทนโดยใช้ <SegmentList> ต่อไปนี้คือตัวอย่าง

<Representation id="FirstRep" bandwidth="2000000" width="1280"
  height="720">
  <BaseURL>FirstRep/</BaseURL>
  <SegmentList timescale="90000" duration="270000">
     <RepresentationIndex sourceURL="representation-index.sidx"/>
     <SegmentURL media="seg-1.ts"/>
     <SegmentURL media="seg-2.ts"/>
     <SegmentURL media="seg-3.ts"/>
  </SegmentList>
</Representation>

สำหรับไฟล์กลุ่มรายการเดียว <SegmentBase> มักใช้กับคำขอช่วงไบต์เพื่อระบุว่าส่วนใดของไฟล์ <BaseURL> ที่มีดัชนี และระบบจะดึงข้อมูลส่วนที่เหลือตามคำขอได้เมื่อเล่นไปเรื่อยๆ หรือการค้นหาเกิดขึ้น ในส่วนนี้ ช่วง Initialization จะระบุช่วงข้อมูลเมตา init และ indexRange ระบุดัชนีสำหรับกลุ่มสื่อ โปรดทราบว่าขณะนี้ เราสนับสนุนเฉพาะช่วงไบต์ที่ต่อเนื่องกันเท่านั้น

<Representation bandwidth="4190760" codecs="avc1.640028"
  height="1080" id="1" mimeType="video/mp4" width="1920">
  <BaseURL>video.mp4<BaseURL>
  <SegmentBase indexRange="674-1149">
    <Initialization range="0-673" />
  </SegmentBase>
</Representation>

ไม่ว่าจะใช้การนำเสนอแบบใด หากสตรีมได้รับการป้องกัน ส่วน <ContentProtection> จะปรากฏในส่วน <AdaptationSet> ที่ schemeIdUri จะระบุระบบ DRM ที่ไม่ซ้ำกันเพื่อใช้งาน คุณใส่รหัสคีย์ (ไม่บังคับ) สำหรับการเข้ารหัสทั่วไปได้

<!-- Common Encryption -->
<ContentProtection
  schemeIdUri="urn:mpeg:dash:mp4protection:2011"
  value="cenc"
  cenc:default_KID="7D2714D0-552D-41F5-AD56-8DD9592FF891">
</ContentProtection>

<!-- Widevine -->
<ContentProtection
  schemeIdUri="urn:uuid:EDEF8BA9-79D6-4ACE-A3C8-27DCD51D21ED">
</ContentProtection>

สำหรับตัวอย่างและรายละเอียดเพิ่มเติม โปรดดูที่ข้อกำหนด MPEG-DASH ด้านล่างนี้เป็นรายการแอตทริบิวต์ DASH เพิ่มเติมในแท็กที่ไม่ได้กล่าวถึงข้างต้นซึ่งเรารองรับอยู่ในปัจจุบัน

ชื่อแอตทริบิวต์ ฟังก์ชันแอตทริบิวต์
mediaPresentationDuration เนื้อหาวิดีโอมีความยาวเท่าใด
minimumUpdatePeriod แอตทริบิวต์ของแท็ก <MPD> ระบุความถี่ที่เราต้องโหลดไฟล์ Manifest ซ้ำ
ประเภท แอตทริบิวต์ของแท็ก <MPD> "ไดนามิก" เพื่อระบุว่านี่คือสตรีมแบบสด
presentationTimeOffset แอตทริบิวต์ของแท็ก <SegmentBase> ระบุการชดเชยเวลาในการนำเสนอจากจุดเริ่มต้นของช่วงเวลา
startNumber ระบุจำนวนสื่อกลุ่มแรกในงานนำเสนอในช่วงเวลาหนึ่ง ซึ่งมักจะใช้ในสตรีมแบบสด

นอกจากนี้เรายังรองรับการใส่กล่อง EMSG ภายใน Fragment MP4 สำหรับ DASH และให้ EmsgEvent แก่นักพัฒนาแอปด้วย

แม้ว่าโปรแกรมเล่นเว็บรีซีฟเวอร์ปัจจุบันของเราจะรองรับ Use Case หลักของ DASH แต่นี่คือรายการแอตทริบิวต์ทั่วไปที่การใช้ DASH ในปัจจุบันไม่สนใจหรือไม่ได้ใช้ ซึ่งหมายความว่าไม่ว่าไฟล์ Manifest จะมีไฟล์ Manifest อยู่หรือไม่ก็ตาม จะไม่มีผลต่อประสบการณ์การเล่นของเนื้อหา

  • availabilityStartTime
  • segmentAlignment

HTTP Live Streaming (HLS)

ดูภาพรวมและข้อกำหนดทั้งหมดของสตรีมมิงแบบสดด้วย HTTP ได้ที่นี่

จุดแข็งที่สำคัญอย่างหนึ่งของ Web Receiver Player คือความสามารถในการรองรับการเล่น HLS ใน MSE HLS จะส่งเพลย์ลิสต์หลักที่มีรายการสตรีมรูปแบบต่างๆ ทั้งหมดพร้อม URL ที่เกี่ยวข้อง ซึ่งต่างจาก DASH ที่ไฟล์ Manifest จะมาอยู่ในไฟล์เดียว เพลย์ลิสต์เวอร์ชันแปรผันคือเพลย์ลิสต์สื่อ แท็ก HLS หลัก 2 รายการที่ Web Receiver Player สนับสนุนในขณะนี้ในเพลย์ลิสต์หลัก ได้แก่

ชื่อแท็ก ฟังก์ชันการทำงาน
#EXT-X-STREAM-INF ระบุสตรีมแบบอัตราบิต/ตัวแปร คุณต้องระบุแอตทริบิวต์ BANDWIDTH ซึ่งรองรับการเลือกสตรีมมิงแบบอัตราบิตที่ปรับเปลี่ยนได้ ขอแนะนำอย่างยิ่งให้ใช้แอตทริบิวต์ CODECS ในการเริ่มต้น MSE เช่น "avc1.42c01e,mp4a.40.2" หากไม่ได้ระบุไว้ ระบบจะใช้เคสเริ่มต้นเป็นวิดีโอ 3.0 ของโปรไฟล์หลัก H264 และเนื้อหาที่เข้ารหัสเสียง "mp4a.40.2"
#EXT-X-MEDIA ระบุเพลย์ลิสต์สื่อเพิ่มเติม (ในแอตทริบิวต์ URI) ที่แสดงถึงเนื้อหา ซึ่งมักเป็นสตรีมเสียงทางเลือกในรูปแบบอื่นๆ (เสียงเซอร์ราวด์ 5.1) หรือภาษา อนุญาตให้ใช้แอตทริบิวต์ของ TYPE ที่มี VIDEO, AUDIO, SUBTITLES หรือ CLOSED-CAPTIONS การตั้งค่าแอตทริบิวต์ DEFAULT เป็น YES จะระบุให้เลือกสตรีมทางเลือกนี้โดยค่าเริ่มต้น

รายการแท็ก HLS ที่ Web Receiver Player สนับสนุนในขณะนี้ในเพลย์ลิสต์สื่อมีดังต่อไปนี้

ชื่อแท็ก ฟังก์ชันการทำงาน
#EXTINF สตรีมข้อมูล ซึ่งโดยปกติจะตามด้วยระยะเวลาของส่วนเป็นวินาที และในบรรทัดถัดไปคือ URL ของส่วนนั้นๆ
#EXT-X-TARGETDURATION ระยะเวลาเป็นวินาทีของแต่ละส่วนคือเวลาใด ซึ่งกำหนดความถี่ที่เราดาวน์โหลด/รีเฟรชไฟล์ Manifest ของเพลย์ลิสต์สำหรับสตรีมแบบสดด้วย Web Receiver ไม่รองรับระยะเวลาที่สั้นกว่า 0.1 วินาที
#EXT-X-MEDIA-SEQUENCE หมายเลขลำดับ (ซึ่งมักจะเป็นของสตรีมแบบสด) ที่แสดงส่วนแรกในเพลย์ลิสต์นี้
#EXT-X-KEY ข้อมูลคีย์ DRM แอตทริบิวต์ METHOD จะช่วยให้เรา ใช้ระบบคีย์ใด วันนี้เรารองรับ AES-128 และ SAMPLE-AES
#EXT-X-BYTERANGE ช่วงไบต์ที่จะดึงข้อมูล URL ของกลุ่ม
#EXT-X-DISCONTINUITY ระบุความไม่ต่อเนื่องระหว่างกลุ่มที่ต่อเนื่องกัน ซึ่งมักพบบ่อยในการแทรกโฆษณาฝั่งเซิร์ฟเวอร์ที่มีกลุ่มโฆษณาปรากฏขึ้นกลางสตรีมหลัก
#EXT-X-PROGRAM-DATE-TIME เวลาสัมบูรณ์ของตัวอย่างแรกของส่วนถัดไป เช่น "2016-09-21T23:23:52.066Z"
#EXT-X-ENDLIST ไม่ว่าจะเป็น VOD หรือสตรีมแบบสด

สำหรับสตรีมแบบสด เราใช้ #EXT-X-PROGRAM-DATE-TIME และ #EXT-X-MEDIA-SEQUENCE เป็นปัจจัยสำคัญในการกำหนดวิธีรวมไฟล์ Manifest ที่เพิ่งรีเฟรช หากมี ระบบจะใช้ #EXT-X-PROGRAM-DATE-TIME เพื่อจับคู่กลุ่มที่รีเฟรช ไม่เช่นนั้นจะใช้หมายเลข #EXT-X-MEDIA-SEQUENCE โปรดทราบว่าตามข้อกำหนดของ HLS เราไม่ได้ใช้การเปรียบเทียบชื่อไฟล์สำหรับการจับคู่

การใช้ HLS ของเรารองรับการเลือกสตรีมเสียงทางเลือก เช่น เสียงเซอร์ราวด์ 5.1 เป็นการเล่นเสียงหลัก ซึ่งทำได้ด้วยการมีแท็ก #EXT-X-MEDIA ที่มีตัวแปลงรหัสทางเลือก รวมถึงการระบุรูปแบบกลุ่มในการกำหนดค่าสตรีม

Web Receiver Player ต้องการการทำงานตามข้อมูลจำเพาะบางอย่าง เช่น หลังแท็ก #EXT-INF เราจะคาดหวัง URI หากไม่ใช่ URI เช่น #EXT-X-DISCOUNTINUITY จะทำให้แยกวิเคราะห์เพลย์ลิสต์ไม่สำเร็จ

ทุกๆ #EXT-X-TARGETDURATION วินาที เราจะโหลดเพลย์ลิสต์/ไฟล์ Manifest ซ้ำเพื่อรับรายการกลุ่มใหม่ และอัปเดตการแสดงกลุ่มทั้งหมดภายในกลุ่มใหม่ ทุกครั้งที่มีการขอการค้นหา เราจะค้นหาเฉพาะภายในช่วงที่ค้นหาได้เท่านั้น สำหรับการถ่ายทอดสด เราอนุญาตให้ค้นหาจากจุดเริ่มต้นของรายการใหม่ที่สุดจนถึงระยะเวลาเป้าหมาย 3 รายการนับตั้งแต่ช่วงท้ายเท่านั้น เช่น หากมีรายการกลุ่ม 10 กลุ่ม และคุณอยู่ในกลุ่มที่ 6 คุณจะค้นหาได้สูงสุด 7 กลุ่ม แต่จะค้นหาไม่เกิน 8 กลุ่ม

การรองรับรูปแบบกลุ่ม

CAF SDK รองรับการเล่นเนื้อหาที่แสดงในรูปแบบที่หลากหลายตามที่อ้างอิงใน HlsSegmentFormat สำหรับเสียงและ HlsVideoSegmentFormat สำหรับวิดีโอ ซึ่งรวมถึงการรองรับเสียงที่แพ็กไว้ เช่น การเล่น AAC และ AC3 ทั้งที่เข้ารหัสและไม่ได้เข้ารหัส คุณจำเป็นต้องระบุข้อมูลนี้ใน MediaInformation ของ LoadRequestData เพื่ออธิบายเนื้อหาของคุณแก่โปรแกรมเล่นอย่างเหมาะสม หากไม่ได้ระบุไว้ การกำหนดค่าโปรแกรมเล่นเริ่มต้นจะพยายามเล่นเนื้อหาเป็นเนื้อหาแพ็กเกจ Transport Stream พร็อพเพอร์ตี้นี้ตั้งค่าจากผู้ส่งรายใดก็ได้ในข้อมูลคำขอโหลด (Android, iOS และเว็บ) หรือภายในตัวรับผ่านตัวดักจับข้อความ

ดูตัวอย่างข้อมูลโค้ดด้านล่างหรือคู่มือการโหลดสื่อโดยใช้ contentId, contentUrl และเอนทิตี เพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีเตรียมเนื้อหาใน Web Receiver

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      ...
      // Specify segment format for an HLS stream playing CMAF packaged content.
      loadRequestData.media.contentType = 'application/x-mpegurl';
      loadRequestData.media.hlsSegmentFormat = cast.framework.messages.HlsSegmentFormat.FMP4;
      loadRequestData.media.hlsVideoSegmentFormat = cast.framework.messages.HlsVideoSegmentFormat.FMP4;
      ...
      return loadRequestData;
    });

การปกป้องเนื้อหา

ตามที่ระบุไว้ในส่วนแท็ก #EXT-X-KEY ข้างต้น Cast SDK รองรับ SAMPLE-AES หรือ SAMPLE-AES-CTR ซึ่งจะระบุ URI ของคีย์ที่สามารถระบุเวกเตอร์การเริ่มต้นได้

EXT-X-KEY: METHOD=SAMPLE-AES, \
URI="data:text/plain;base64,XXXXXX", \
IV=0x6df49213a781e338628d0e9c812d328e, \
KEYFORMAT="com.widevine", \
KEYFORMATVERSIONS="1"

KEYFORMAT ที่เรารองรับตอนนี้คือ Widevine และ URI มีข้อมูล DRM ที่เข้ารหัส BASE64 XXXXXXX ซึ่งเมื่อถอดรหัสจะมีรหัสคีย์ดังนี้

{
   "content_id": "MTQ1NjkzNzM1NDgxNA==",
   "key_ids": [
      "xxxxxxxxxxxxxxxx"
   ]
}

เวอร์ชัน 1 กำหนดแอตทริบิวต์ต่อไปนี้

แอตทริบิวต์ ตัวอย่าง คำอธิบาย
KEYFORMATVERSIONS "1" ข้อเสนอนี้กำหนดรูปแบบคีย์เวอร์ชัน 1
KEYFORMAT "urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed" UUID คือ UUID Widevine จาก DASH IF IOP ใช้สตริงเดียวกันใน MPD กับสตรีมที่เข้ารหัส ไวด์ไวน์
URI "data:text/plain;base64, <base64 encoded PSSH box>" URI ของสตรีมที่มีประเภทข้อมูลและช่อง PSSH
METHOD SAMPLE-AES-CTR ระบุวิธีการเข้ารหัสที่ใช้เมื่อเข้ารหัสเนื้อหา SAMPLE-AES ส่งสัญญาณว่าเนื้อหาได้รับการเข้ารหัสโดยใช้ "cbcs" ตัวอย่าง-AES-CTR จะระบุว่าเนื้อหาได้รับการเข้ารหัสโดยใช้รูปแบบการป้องกัน AES-CTR รูปแบบใดรูปแบบหนึ่ง ซึ่งก็คือ "cenc"

แอตทริบิวต์ที่แมปกับ DASH MPD:

แอตทริบิวต์ คำอธิบาย
KEYFORMAT แอตทริบิวต์ SchemeIdUri ขององค์ประกอบ ContentProtection
URI เนื้อหาขององค์ประกอบ cenc:pssh
KEYID สตริงฐานสิบหก 16 ไบต์ที่เข้ารหัสรหัสคีย์ซึ่งมีบทบาทเหมือนกับ default_kid ใน MPEG DASH หากใช้รูปแบบคีย์แบบลำดับชั้น คีย์นี้จะเป็นคีย์ "รูท"

ตัวอย่างเพลย์ลิสต์ HLS ที่มีสัญญาณ V2

#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:2
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-MAP:URI="init_segment.mp4"
#EXTINF:1.001,
output_video-1.mp4
#EXT-X-DISCONTINUITY
#EXT-X-KEY:METHOD=SAMPLE-AES,URI="data:text/plain;base64,AAAAPXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAB0aDXdpZGV2aW5lX3Rlc3QiDHRlc3QgY29udGVudA==",KEYID=0x112233445566778899001122334455,KEYFORMAT="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed",KEYFORMATVERSION="1"
#EXTINF:1.001,
output_video-2.mp4
#EXTINF:0.734,
output_video-3.mp4
#EXT-X-ENDLIST

ด้านล่างนี้เป็นรายการฟีเจอร์และแท็กใน HLS ที่เราไม่ได้ใช้งานหรือรองรับในปัจจุบัน ทั้งนี้ การมีอยู่หรือไม่มีอยู่ของสตรีมแบบสดจะไม่มีผลต่อพฤติกรรมการสตรีม

  • แอตทริบิวต์ RESOLUTION= ใน #EXT-X-STREAM-INF จะถูกละเว้น
  • ไม่ได้ใช้แอตทริบิวต์ AUTOSELECT= ใน #EXT-X-MEDIA แต่เราอาศัย DEFAULT= แทน
  • ระบบจะไม่สนใจ #EXT-X-I-FRAME-STREAM-INF ในเพลย์ลิสต์หลัก
  • ไม่สนใจ #EXT-X-DISCONTINUITY-SEQUENCE แล้ว
  • #EXT-X-PLAYLIST-TYPE:EVENT ปรากฏในสตรีมแบบสดได้และ #EXT-X-PLAYLIST-TYPE:VOD สามารถแสดงในสตรีม VOD ได้ แต่ปัจจุบัน Web Receiver Player อาศัยเพียง #EXT-X-ENDLIST เพื่อตัดสินการถ่ายทอดสดกับ VOD เท่านั้น

สตรีมมิงอย่างราบรื่น

ข้อมูลจำเพาะของ Smooth Streaming อย่างเป็นทางการของ Microsoft

การสตรีมที่ราบรื่นมีโปรโตคอลสตรีมมิงแบบปรับอัตโนมัติและข้อกำหนด XML ผ่าน HTTP (คล้ายกับ DASH) Smooth Streaming แนะนำให้ใช้แพ็กเกจ MPEG-4 สำหรับสื่อเป็นกลุ่มเท่านั้น ซึ่งแตกต่างจาก DASH

ตารางต่อไปนี้เป็นตารางของแท็กและแอตทริบิวต์ที่ใช้กันมากที่สุดใน Smooth Streaming ซึ่ง Web Receiver Player รองรับในปัจจุบัน มีคำอธิบายแนวคิดหลายอย่างอยู่แล้วในส่วน DASH ข้างต้น

แท็ก/แอตทริบิวต์ การใช้งาน
<SmoothStreamingMedia> แท็กหลักสำหรับไฟล์ Manifest มีแอตทริบิวต์ต่อไปนี้
  • TimeScale: จำนวนหน่วยที่ใช้แทน 1 วินาที โดยทั่วไปจะเพิ่มขึ้น 10,000,000
  • ระยะเวลา: ความยาวของเนื้อหาตามเวลา โปรแกรมเล่นเว็บรีซีฟเวอร์ไม่รองรับระยะเวลาสั้นกว่า 0.1 วินาที
  • IsLive: ไฟล์ Manifest เป็นสื่อแบบสดไหม
<StreamIndex> สตรีม 1 ชุด ซึ่งคล้ายกับ AdaptationSet ของ DASH ประเภทมักจะเป็น "ข้อความ" "วิดีโอ" หรือ "เสียง" แอตทริบิวต์ URL มักมี URL ส่วนย่อยที่เป็นเทมเพลต โดยใช้ข้อมูล เช่น อัตราบิตหรือเวลาเริ่มต้น
<QualityLevel> แท็ก QualityLevel แต่ละแท็กจะระบุบิตเรตและตัวแปลงรหัส FourCC โค้ด FourCC มักจะเป็น "H264", "AVC1", "AACL" ฯลฯ ส่วนวิดีโอจะระบุความละเอียดผ่าน MaxWidth และ MaxHeight สำหรับเสียง จะระบุความถี่ (เช่น 44100) ผ่าน SamplingRate และจำนวนช่องสัญญาณ
<c> องค์ประกอบส่วนย่อยของสตรีม ประเภทมีดังนี้
  • d: ระยะเวลาของส่วนย่อย
  • t: เวลาสื่อของส่วนย่อย
<การป้องกัน> แท็กที่มีแอตทริบิวต์ SystemID ที่ไม่บังคับ ซึ่งแสดงรหัสของระบบ DRM ที่จะใช้ภายใต้แท็ก <SmoothStreamingMedia>
<ProtectionHeader> ในส่วน <Protection> อาจมีแอตทริบิวต์ของ SystemID และข้อมูลที่กำหนดเอง ซึ่งโดยปกติแล้วจะเข้ารหัส Base64 ส่วน Widevine จะมีรหัสคีย์, ความยาวของคีย์, รหัสอัลกอริทึม เช่น AESCTR, LA_URL (URL การซื้อใบอนุญาต), LUI_URL (URL อินเทอร์เฟซผู้ใช้ของใบอนุญาต) และ DS_ID (รหัสบริการโดเมน)

การปกป้องเนื้อหา

โปรดใช้การแมปด้านล่างเพื่อเข้ารหัสรหัสระบบป้องกันอย่างถูกต้อง

  • WIDEVINE: "EDEF8BA9-79D6-4ACE-A3C8-27DCD51D21ED",
  • CLEARKEY: '1077EFEC-C0B2-4D02-ACE3-3C1E52E2FB4B',
  • MPEG_DASH_MP4PROTECTION: "URN:MPEG:DASH:MP4PROTECTION:2011"

สำหรับ <ProtectionHeader> ด้านล่างนี้คือตัวอย่างข้อมูลที่เข้ารหัส Base64 เมื่อถอดรหัสแล้ว ข้อมูลจะอยู่ในรูปแบบที่ถอดรหัสเดียวกันตามที่อธิบายไว้ในการสนับสนุนการปกป้องเนื้อหา DASH ข้างต้น

<Protection>
  <ProtectionHeader SystemID="9a04f079-9840-4286-ab92-e65be0885f95">
    $BASE64ENCODED_DATA
  </ProtectionHeader>
</Protection>

ด้านล่างนี้เป็นตัวอย่างไฟล์ Manifest สำหรับสตรีมอย่างลื่นไหลแบบสดที่มีเนื้อหายาว 3,000 วินาที

<?xml version="1.0"?>
  <SmoothStreamingMedia MajorVersion="2" MinorVersion="0" Duration="3000000000"
    TimeScale="10000000" IsLive="TRUE" LookAheadFragmentCount="2" DVRWindowLength="600000000" CanSeek="TRUE" CanPause="TRUE">
    <StreamIndex Type="text" Name="textstream301_swe" Language="swe" Subtype="CAPT" Chunks="0"
      TimeScale="10000000" Url="QualityLevels({bitrate})/Fragments(textstream301_swe={start time})">
      <QualityLevel Index="0" Bitrate="20000" CodecPrivateData="" FourCC="DFXP"/>
        <c d="40000000" t="80649382288125"/>
        <c d="39980000"/>
        <c d="40020000"/>
    </StreamIndex>
    <Protection>
      <ProtectionHeader> SystemID="$BASE64ENCODEDDRMDATA$"</ProtectionHeader>
    </Protection>
    <StreamIndex Type="audio" Name="audio101_eng" Language="eng" Subtype="AACL" Chunks="0"
      TimeScale="10000000" Url="QualityLevels({bitrate})/Fragments(audio101_eng={start time})">
      <QualityLevel Index="0" Bitrate="128000" CodecPrivateData="1290" FourCC="AACL" AudioTag="255"
        Channels="2" SamplingRate="32000" BitsPerSample="16" PacketSize="4"/>
      <c d="40000000" t="80649401327500"/>
      <c d="40000000"/>
      <c d="40000000"/>
    </StreamIndex>
    <StreamIndex Type="video" Name="video" Subtype="AVC1" Chunks="0" TimeScale="10000000"
      Url="QualityLevels({bitrate})/Fragments(video={start time})">
      <QualityLevel Index="0" Bitrate="400000" CodecPrivateData="000000016742E01596540C0EFCB808140000000168CE3880"
        FourCC="AVC1" MaxWidth="384" MaxHeight="216"/>
      <QualityLevel Index="1" Bitrate="800000" CodecPrivateData="00000001674D401E965281004B6020500000000168EF3880"
        FourCC="AVC1" MaxWidth="512" MaxHeight="288"/>
      <QualityLevel Index="2" Bitrate="1600000" CodecPrivateData="00000001674D401E965281B07BCDE020500000000168EF3880"
        FourCC="AVC1" MaxWidth="854" MaxHeight="480"/>
      <QualityLevel Index="3" Bitrate="2200000" CodecPrivateData="00000001674D401F96528080093602050000000168EF3880"
        FourCC="AVC1" MaxWidth="1024" MaxHeight="576"/>
      <c d="40000000" t="80649401378125"/>
      <c d="40000000"/>
      <c d="40000000"/>
    </StreamIndex>
  </SmoothStreamingMedia>

ในตัวอย่างด้านบนสำหรับสตรีมวิดีโอ เทมเพลต URL คือ

QualityLevels({bitrate})/Fragments(video={start time})

ดังนั้น 2 ส่วนแรก (สมมติว่าเราอยู่ที่ระดับคุณภาพดัชนี 2) จะเป็นดังนี้ โดยเวลาเริ่มต้นที่ดึงมาจาก t="80649401378125" ในส่วน StreamIndex วิดีโอ และการเพิ่มเวลา 4 วินาที * 10000000 ต่อกลุ่ม:

QualityLevels(2)/Fragments(video=80649401378125)
QualityLevels(2)/Fragments(video=80649441378125)
...

ต่อไปนี้เป็นรายการแอตทริบิวต์ของ Smooth Streaming ที่เราไม่สนใจและไม่มีผลต่อประสบการณ์สตรีมมิง ไม่ว่าจะระบุหรือไม่ก็ตาม

  • CanSeek, CanPause ในแท็ก <SmoothStreamingMedia>
  • Chunks, QualityLevels ในแท็ก <StreamIndex> แต่เราจะคำนวณจำนวนกลุ่มและจำนวนระดับคุณภาพตามข้อมูลที่ให้ไว้ภายใน <StreamIndex> เช่น แท็ก QualityLevel จริงและแท็ก <c>
  • ไม่ได้ใช้ BitsPerSample, PacketSize ใน <QualityLevel>

ตรวจสอบประเภทการแสดงผล

เมธอด canDisplayType จะตรวจสอบความสามารถด้านวิดีโอและเสียงของอุปกรณ์ Web Receiver และการแสดงผลโดยการตรวจสอบความถูกต้องของพารามิเตอร์สื่อที่ส่งผ่าน โดยแสดงผลบูลีน พารามิเตอร์ทั้งหมดยกเว้นพารามิเตอร์แรกเป็นตัวเลือกที่ไม่บังคับ ยิ่งคุณใส่พารามิเตอร์มากเท่าไหร่ การตรวจสอบก็ยิ่งแม่นยำมากขึ้นเท่านั้น

ลายเซ็นคือ canDisplayType(<em>mimeType</em>,<em>codecs</em>,<em>width</em>,<em>height</em>,<em>framerate</em>)

ตัวอย่างเช่น

ตรวจสอบว่าอุปกรณ์และจอแสดงผล Web Receiver รองรับวิดีโอ/mp4 mimetype ที่มีตัวแปลงรหัส ขนาด และอัตราเฟรมเฉพาะนี้หรือไม่

canDisplayType("video/mp4", "avc1.42e015,mp4a.40.5", 1920, 1080, 30)

ตรวจสอบว่าอุปกรณ์ Web Receiver และจอแสดงผลรองรับรูปแบบวิดีโอ 4K สำหรับตัวแปลงรหัสนี้โดยการระบุความกว้าง 3840 และความสูง 2160 โดยทำดังนี้

canDisplayType("video/mp4", "hev1.1.2.L150", 3840, 2160)

ตรวจสอบว่าอุปกรณ์เว็บรีซีฟเวอร์และจอแสดงผลรองรับ HDR10 สำหรับตัวแปลงรหัส ขนาด และอัตราเฟรมนี้หรือไม่

canDisplayType("video/mp4", "hev1.2.6.L150", 3840, 2160, 30)

ตรวจสอบว่าอุปกรณ์ Web Receiver และจอแสดงผลสนับสนุน Dolby Vision (DV) สำหรับตัวแปลงรหัส ขนาด และอัตราเฟรมนี้หรือไม่

canDisplayType("video/mp4", "dvhe.04.06", 1920, 1080, 30)

DRM

เนื้อหาสื่อบางอย่างต้องใช้การจัดการสิทธิ์ด้านดิจิทัล (DRM) สำหรับเนื้อหาสื่อที่มีใบอนุญาต DRM (และ URL คีย์) ที่จัดเก็บไว้ในไฟล์ Manifest (DASH หรือ HLS) Cast SDK จะจัดการเคสนี้ให้คุณ ชุดย่อยของเนื้อหาดังกล่าวต้องใช้ licenseUrl ซึ่งจำเป็นสำหรับการรับคีย์การถอดรหัส ใน Web Receiver คุณสามารถใช้ PlaybackConfig เพื่อตั้งค่า licenseUrl ได้ตามต้องการ

ข้อมูลโค้ดต่อไปนี้จะแสดงวิธีตั้งค่าข้อมูลคำขอสำหรับคำขอใบอนุญาต เช่น withCredentials

const context = cast.framework.CastReceiverContext.getInstance();
const playbackConfig = new cast.framework.PlaybackConfig();
// Customize the license url for playback
playbackConfig.licenseUrl = 'http://widevine/yourLicenseServer';
playbackConfig.protectionSystem = cast.framework.ContentProtection.WIDEVINE;
playbackConfig.licenseRequestHandler = requestInfo => {
  requestInfo.withCredentials = true;
};
context.start({playbackConfig: playbackConfig});

// Update playback config licenseUrl according to provided value in load request.
context.getPlayerManager().setMediaPlaybackInfoHandler((loadRequest, playbackConfig) => {
  if (loadRequest.media.customData && loadRequest.media.customData.licenseUrl) {
    playbackConfig.licenseUrl = loadRequest.media.customData.licenseUrl;
  }
  return playbackConfig;
});

หากคุณมีการผสานรวม Google Assistant ข้อมูลบางอย่าง DRM เช่น ข้อมูลเข้าสู่ระบบที่จำเป็นสำหรับเนื้อหา อาจลิงก์กับบัญชี Google ของคุณโดยตรงผ่านกลไกต่างๆ เช่น OAuth/SSO ในกรณีดังกล่าว หากเนื้อหาสื่อโหลดผ่านเสียงหรือมาจากระบบคลาวด์ จะมีการเรียกใช้ setCredentials จากระบบคลาวด์ไปยังอุปกรณ์แคสต์ที่ให้ข้อมูลรับรองดังกล่าว จากนั้นแอปพลิเคชันที่เขียนแอป Web Receiver จะใช้ข้อมูล setCredentials เพื่อดำเนินการ DRM ตามความจำเป็น ด้านล่างนี้เป็นตัวอย่างของการใช้เอกสารรับรองในการสร้างสื่อ

เคล็ดลับ: โปรดดูการโหลดสื่อโดยใช้ contentId, contentUrl และเอนทิตีด้วย

การจัดการช่องเสียง

เมื่อโปรแกรมเล่นแคสต์โหลดสื่อ ระบบจะตั้งค่าบัฟเฟอร์แหล่งที่มาของเสียงแหล่งเดียว ในขณะเดียวกัน ก็ยังเลือกตัวแปลงรหัสที่เหมาะสมที่จะใช้โดยบัฟเฟอร์ โดยอิงตามประเภท MIME ของแทร็กหลัก ตั้งค่าบัฟเฟอร์และตัวแปลงรหัสใหม่แล้ว:

  • เมื่อวิดีโอเริ่มเล่น
  • ที่ทุกช่วงพักโฆษณา และ
  • ทุกครั้งที่เนื้อหาหลักกลับมาเล่นต่อ

เนื่องจากบัฟเฟอร์ใช้ตัวแปลงรหัสตัวเดียวและตัวแปลงรหัสถูกเลือกโดยอิงตามแทร็กหลัก จึงมีสถานการณ์ที่อาจมีการกรองแทร็กรองออกและไม่ได้ยินเสียง ปัญหานี้อาจเกิดขึ้นเมื่อแทร็กหลักของโปรแกรมสื่อ อยู่ในเสียงเซอร์ราวด์ แต่แทร็กเสียงที่ 2 ใช้เสียงสเตอริโอ เนื่องจากแทร็กรองมักถูกใช้เพื่อนำเสนอเนื้อหาในภาษาอื่น การจัดหาสื่อที่มีแทร็กจำนวนมากจึงอาจมีผลกระทบอย่างมาก เช่น ผู้ชมจำนวนมากไม่ได้ยินเนื้อหาในภาษาท้องถิ่นของตน

สถานการณ์ต่อไปนี้แสดงให้เห็นความสำคัญของการจัดโปรแกรมโดยที่แทร็กหลักและแทร็กรองมีจำนวนช่องเท่ากัน

สถานการณ์ 1 - สตรีมสื่อขาดความเท่าเทียมของช่องทางในแทร็กหลักและแทร็กรอง

  • อังกฤษ - AC-3 เวอร์ชัน 5.1 (หลัก)
  • ภาษาสวีเดน - AAC 2-channel
  • ฝรั่งเศส - AAC 2 ช่อง
  • เยอรมัน - AAC 2 ช่อง

ในสถานการณ์นี้ หากตั้งค่าภาษาของผู้เล่นเป็นภาษาอื่นที่ไม่ใช่ภาษาอังกฤษ ผู้ใช้จะไม่ได้ยินแทร็กที่คาดว่าจะได้ยิน เนื่องจากแทร็ก 2 ช่องทั้งหมดจะถูกกรองออกระหว่างการเล่น แทร็กเดียวที่คุณเล่นได้คือ AC-3 5.1-channel หลัก และเฉพาะเมื่อตั้งค่าภาษาเป็นภาษาอังกฤษ

สถานการณ์ 2 - สตรีมสื่อที่มีความเท่าเทียมกันของช่องทางในแทร็กหลักและแทร็กรอง

  • อังกฤษ - AC-3 เวอร์ชัน 5.1 (หลัก)
  • สวีเดน - AC-3 5.1 Channel
  • ฝรั่งเศส - AC-3 ช่อง 5.1
  • เยอรมัน - ช่อง AC-3 5.1

เนื่องจากแทร็กของสตรีมนี้มีจำนวนช่องเท่ากัน ผู้ชมจะได้ยินแทร็กโดยไม่คำนึงถึงภาษาที่เลือกไว้

การจัดการช่องสัญญาณเสียงของ Shaka

โปรแกรมเล่น Shaka (DASH) มีค่าเริ่มต้นเป็นจำนวนช่องที่ต้องการ 2 ช่อง เพื่อเป็นมาตรการบรรเทาเมื่อพบกับสื่อที่ขาดความเท่าเทียมในแทร็กเสียงรอง

หากแทร็กหลักไม่ใช่เสียงเซอร์ราวด์ (เช่น แทร็กสเตอริโอ 2 ช่อง) โปรแกรมเล่น Shaka จะมีช่องสัญญาณเสียง 2 ช่องโดยค่าเริ่มต้น และกรองแทร็กสื่อรองที่มีมากกว่า 2 ช่องโดยอัตโนมัติ

นอกจากนี้ คุณยังกำหนดค่าจำนวนช่องเสียงที่ต้องการของ Shaka ได้ด้วยการตั้งค่า preferredAudioChannelCount ในพร็อพเพอร์ตี้ shakaConfig ใน cast.framework.PlaybackConfig

เช่น

shakaConfig = { "preferredAudioChannelCount": 6 };

เมื่อตั้ง preferredAudioChannelCount เป็น 6 โปรแกรมเล่น Shaka จะตรวจสอบว่าสามารถรองรับตัวแปลงรหัสเสียงเซอร์ราวด์ (AC-3 หรือ EC-3) ได้ไหม และกรองแทร็กสื่อที่ไม่สอดคล้องกับจำนวนช่องสัญญาณที่ต้องการออกโดยอัตโนมัติ