はじめに

こんにちは streampack チームのメディです。
https://cloudpack.jp/service/option/streampack.html

Copyrights

Sintel
© copyright Blender Foundation | www.sintel.org

What is CMAF ・ CMAFとは

CMAF means Common media application format
In order to simplify let’s say that CMAF has support for both MPEG-DASH and HLS. You just need to create your video segments once. Both of the manifests (MPD & m3u8) will use the same video segments.

CMAFは「Common media application format」を意味します。
単純化するため、CMAFがMPEG-DASHとHLSの両方をサポートしているとしましょう。 あなたは一度あなたのビデオセグメントを作成する必要があります。 両方のマニフェスト(MPDm3u8)は同じビデオセグメントを使用します。

Objective・目的

Learning how to create a CMAF compliant on demand video stream.
オンデマンドのCMAFのビデオストリームの簡単な例を学ぶこと。

Tools ・ツール

FFMPEG

FFMPEG will encode the video file.
FFMPEGはビデオファイルをエンコードします。
I am using a static build of FFMPEG v4.1.
FFMPEG「v4.1」の静的ビルドを使用しています。

FFMPEG static builds ・ FFMPEG静的ビルド

Bento4

Bento will create CMAF fragmented MP4 files with the associated manifests for HLS and MPEG-Dash.
Bentoは、HLSおよびMPEG-Dashの関連するマニフェストを含むCMAF断片化された MP4 ファイルを作成します。
https://github.com/axiomatic-systems/Bento4

CMAF creation on OSX ・ OSXでのCMAFの作成方法

brew install p7zip
wget https://evermeet.cx/ffmpeg/ffmpeg-4.1.7z
7za x  ffmpeg-4.1.7z
rm ffmpeg-4.1.7z

I was not able to use the Bento4 builds for my system, so I had to compile it.
Bento4ビルドを私のシステムに使用することができなかったため、コンパイルする必要がありました。

If you want to try the Bento4 builds for your system, please check this page.
あなたのシステム用のBento4ビルドを試したい場合は、このページをチェックしてください。

cd
mkdir cmaf 
cd cmaf
git init 
git clone https://github.com/axiomatic-systems/Bento4.git

In the Bento4 folder please open the following file with Xcode :
Bento4フォルダにXcodeで次のファイルを開きます:
Build/Targets/universal-apple-macosx/Bento4.xcodeproj
Then click: Product > Build
次に、Product> Buildをクリックします。

In this example, we use Xcode on OSX, for other systems & IDE, please refer to this page
この例では、OSX上でXcodeを使用しています。他のシステムとIDEについては、このページを参照してください。

By default, on OSX, your builds will be located in:
デフォルトでは、OSXではビルドは次の場所にあります。
~/Library/Developer/Xcode/DerivedData/

For example in my case, the full path of the build directory is:
たとえば私の場合、ビルドディレクトリのフルパスは次のようになります。

/Users/mehdi/Library/Developer/Xcode/DerivedData/Bento4-csvbfwwtinqvwpdlscgeezmabnlx/Build/Products/Debug

Shell script ・ シェルスクリプト

This shell script will use FFMPEG & Bento4 to generate a CMAF stream from a mp4 video.
このシェルスクリプトは、FFMPEGとBento4を使用して mp4 ビデオからCMAFストリームを生成します。

#! /bin/sh

# Current working directory
cwd="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
file="${cwd}/sintel-1024-surround.mp4"
timestamp=`date +%s`
ffmpeg="${cwd}/ffmpeg" #v 4.1.
vb_array=(500 1000 2000) # video bitrates in kbps
x264encoder="libx264"  # software encoder : libx264 , OSX hardware acceleration : h264_videotoolbox
#You REALLY should use hardware acceleration :-)  https://trac.ffmpeg.org/wiki/HWAccelIntro

#TODO CHANGE FILE PATH
mp4dash="/Users/mehdi/cmaf/Bento4/Source/Python/utils/mp4-dash.py" # v1.5.1-627
#TODO CHANGE FILE PATH
bento4Builds="/Users/mehdi/Library/Developer/Xcode/DerivedData/Bento4-csvbfwwtinqvwpdlscgeezmabnlx/Build/Products/Debug" # Compiled with Xcode

echo "Creating a working directory :  $timestamp"
mkdir -p "${timestamp}"

echo "Creating an output directory  : output/${timestamp}"
mkdir -p "output/${timestamp}"

echo "Audio extraction & encoding"
ffmpeg -i "${file}" \
-f mp4 -map 0:1 -movflags frag_keyframe+empty_moov+default_base_moof+faststart  -vn -strict experimental -c:a aac -b:a 128k -f mp4 -frag_duration 4000000 "${timestamp}"/audio_only.fmp4


echo "Video extraction & encoding"
for bitrate in "${vb_array[@]}"; do
     ffmpeg -i "${file}" \
     -f mp4 -map 0:0 -movflags frag_keyframe+empty_moov+default_base_moof+faststart -bf 2 -g 90 -sc_threshold 0 -an -strict experimental -profile:v baseline -frag_duration 4000000  -c:v "${x264encoder}" -b:v "${bitrate}k" "${timestamp}"/video_only_"${bitrate}"k.fmp4
done

echo "Creating CMAF VOD streams"
${mp4dash}  -f -o ${cwd}/output/${timestamp} -v --hls --profiles=onDemand --use-segment-timeline ${cwd}/${timestamp}/*.fmp4  --exec-dir=${bento4Builds}

echo "Your files have been saved in ${cwd}/output/${timestamp}"

Created files ・ 作成されたファイル

In video/avc1 we have 3 folders, because we chose 3 different video bitrates (500, 1000 & 2000 kbps).
video/avc1 では、3つの異なるビデオビットレート(500,1000,2000 kbps)を選択しているので、3つのフォルダがあります。

Javascript player : Plyr

Plyr is an open sources javascript media player.
Plyr はオープンソースのjavascriptメディアプレーヤーです。

If you are interested in Plyr, I wrote a more detailed article.
Plyr に興味がある場合は、より詳細な記事にあります。

Note about old web browsers ・ 古いウェブブラウザについて

To support old browsers, I use the polyfill version of plyr.
古いブラウザをサポートするために、plyr の polyfill 版を使用します。

<!-- Plyr -->
  <script src="//cdn.plyr.io/3.4.7/plyr.polyfilled.js"></script>

I also hide the big central button onPlay to avoid issues on some browsers.
いくつかのWebブラウザでの不具合を避けるために、onPlay イベントが発生したときに大きな再生ボタンを非表示にします。

// To support old browsers, you may want to hide the big central play button. 
  document.getElementsByClassName('plyr__control--overlaid')[0].style.visibility = 'hidden';

Implementation ・ 実装

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>Plyr CMAF</title>
  <!-- Plyr style sheet -->
  <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/plyr/3.4.7/plyr.css" />
</head>

<body>
  <!-- HLS support -->
  <script src="//cdn.jsdelivr.net/hls.js/latest/hls.js"></script>
  <!-- MPEG Dash support -->
  <script src="//cdnjs.cloudflare.com/ajax/libs/dashjs/2.9.2/dash.all.debug.js"></script>
  <!-- Plyr -->
  <script src="//cdn.plyr.io/3.4.7/plyr.polyfilled.js"></script>


  <video preload="none" id="player" controls crossorigin>
    <!-- **** Don't forget to change the source paths ! **** -->
    <source src="output/1545184765/master.m3u8" type="application/x-mpegURL">
    <source src="output/1545184765/stream.mpd" type="application/dash+xml">
  </video>

</body>
<script type="text/javascript">
  var isDebug = true;
  var video = document.querySelector('#player');
  var sources = video.getElementsByTagName('source');

  // Detecting browser capabilities
  var canUseDash = false;
  var obj = document.createElement('video');
  if (obj.canPlayType('application/dash+xml')) {
    canUseDash = true;
  }

  if (canUseDash) {
    // MPEG-DASH
    var mpd = sources[1].src
    var dash = dashjs.MediaPlayer().create();
    dash.initialize(video, mpd, false);

  } else {
    // HLS
    var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);

    // Safari supports HLS natively, we don't want to use HLS.js
    if (!isSafari && Hls.isSupported()) {
      var hlsSrc = sources[0].src;
      var hls = new Hls();
      hls.loadSource(hlsSrc);
      hls.attachMedia(video);
    }
  }

  var player = new Plyr(video, {
    resetOnEnd: true,
    debug: isDebug
  });

  // To avoid  problems on old browsers, you may want to hide the big central play button when onPlay if fired
  player.on('play', function(e) {
    document.getElementsByClassName('plyr__control--overlaid')[0].style.visibility = 'hidden';
  });


  player.on('pause', function(e) {
    document.getElementsByClassName('plyr__control--overlaid')[0].style.visibility = '';
  });


</script>

</html>

Compatibility ・ウェブブラウザの互換性

Windows specific browsers

Windows Version Browser Compatibility
Windows 10 EDGE (15,16,17,18) YES
Windows 10 Internet Explorer 11 YES
Windows 8.1 Internet Explorer 11 YES
Windows 7 Internet Explorer 11 NO 🙁

Mac OS specific browsers

OSX Version Browser Compatibility
Mojave Safari 12 YES
High Sierra Safari 11.1 YES
Sierra Safari 10.1 YES
ElCapitan Safari 9.1 YES

Multi platform desktop browsers

Browser Compatibility
Firefox 45 YES
Firefox 64 YES
Chrome 40 YES
Chrome 71 YES

Android

OS Version Browser Compatibility
Android 4.4 Chrome: YES
Android 4.4 Firefox: YES
Android 8 Chrome: YES
Android 8 Firefox: YES

iOS

OS Version Browser Compatibility
iOS 12 Safari 12 YES
iOS 12 Chrome: YES
iOS11 Safari 12 YES
iOS 11 Chrome YES
iOS 10 Safari 10 YES
iOS 10 Chrome YES
iOS 9 Safari 9 NO 🙁
iOS 9 Chrome NO 🙁

Sources

Tools

http://bento4.com/documentation
https://www.ffmpeg.org/ffmpeg-all.html

A more complete CMAF creation script

https://gist.github.com/GnaphronG/ad239570c47141d89a9282913607d83f

Player capabilities detection

https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/canPlayType

Plyr javascript media player

https://github.com/sampotts/plyr

CMAF with AWS MediaConvert

https://qiita.com/tomopyonsama/items/e4d58af20928cab41cb5

About CMAF

https://blogs.akamai.com/2016/06/cmaf-what-it-is-and-why-it-may-change-your-ott-future.html
https://blogs.akamai.com/jp/2018/04/cmaf-cmaf-low-lalatency-live.html
https://developer.apple.com/documentation/http_live_streaming/about_the_common_media_application_format_with_http_live_streaming
https://bitmovin.com/what-is-cmaf-threat-opportunity/

元記事はこちら

無料でVODのCMAF(HLS + MPEG-DASH)の作成方法