はじめに
こんにちは。ブームにやや乗り遅れましたが呪術廻戦にハマってしまったstreampackのfadoです。華金は楽しみがいっぱいです。
さて、今までWowza Streaming Engine
を使って作業している時は、管理画面(Wowza Streaming Engine Manager
)にログインし、ポチポチしていました。それだと確かにGUIは楽なのですがAPIでの制御を必要とする業務があり、慌てて色々調べ始めると言ったことがありました。そこで今回の記事では、その経験を踏まえて、自分なりに理解したApplicationの作成やプロパティの追加などの作業について簡単に解説していきたいと思います。ちなみにApplicationとはメデイアストリーミングに関する様々な制御、プロパティを定義する、Wowza Streaming Engine
において核となる部分です。作成する画面はこのような感じですね。
注意事項
-
Wowza Streaming Engine
(以下Wowza
) - サーバーは
AWS
環境で構築したもの - バージョン4.8.9 (build 20201221171606)
- 認証方法はbasicです
-
Wowza
についてある程度知見のある方々が対象です。 -
Wowza
のREST API
インターフェースはデフォルトで8087ポート/tcpを利用しているため、SGやFirewallを予め開放して下さい。
手順
Applicationを作成
Application Name(appName): livetest
Application Type: Live HTTP Origin
Server Name(serverName): _defaultServer_
VHost Name(vhostName): _defaultVHost_
-
メソード
-
POST
-
パス
-
/v2/servers/{serverName}/vhosts/{vhostName}/applications/{appName}
-
リクエスト
$ curl -u "xxxx:yyyy" -X POST -H 'Accept:application/json; charset=utf-8' -H 'Content-Type:application/json; charset=utf-8' http://XXX.XXX.XXX.XXX:8087/v2/servers/_serverName_/vhosts/_defaultVHost_/applications -d @livetest.json
- レスポンス
{"success":true,"message":"Application (livetest) created successfully.","data":null}
{
"name": "livetest",
"version": "",
"serverName": "_defaultServer_",
"appType": "LiveHTTPOrigin",
"applicationTimeout": 0,
"pingTimeout": 0,
"clientStreamReadAccess": "*",
"clientStreamWriteAccess": "*",
"avSyncMethod": "senderreport",
"maxRTCPWaitTime": 12000,
"httpCORSHeadersEnabled": true,
"httpStreamers": [
"sanjosestreaming",
"cupertinostreaming",
"smoothstreaming",
"mpegdashstreaming"
],
"mediaReaderRandomAccessReaderClass": "",
"httpOptimizeFileReads": false,
"mediaReaderBufferSeekIO": false,
"captionLiveIngestType": "",
"vodTimedTextProviders": [
"vodcaptionprovidermp4_3gpp"
],
"securityConfig": {
"serverName": "_defaultServer_",
"secureTokenVersion": 0,
"clientStreamWriteAccess": "*",
"publishRequirePassword": true,
"publishPasswordFile": "",
"publishRTMPSecureURL": "",
"publishIPBlackList": "",
"publishIPWhiteList": "",
"publishBlockDuplicateStreamNames": false,
"publishValidEncoders": "",
"publishAuthenticationMethod": "digest",
"playMaximumConnections": 0,
"playRequireSecureConnection": false,
"secureTokenSharedSecret": "",
"secureTokenUseTEAForRTMP": false,
"secureTokenIncludeClientIPInHash": false,
"secureTokenHashAlgorithm": "",
"secureTokenQueryParametersPrefix": "",
"secureTokenOriginSharedSecret": "",
"playIPBlackList": "",
"playIPWhiteList": "",
"playAuthenticationMethod": "none"
},
"streamConfig": {
"serverName": "_defaultServer_",
"streamType": "live",
"storageDir": "${com.wowza.wms.context.VHostConfigHome}/content",
"createStorageDir": false,
"storageDirExists": true,
"keyDir": "${com.wowza.wms.context.VHostConfigHome}/keys",
"liveStreamPacketizer": [
"cupertinostreamingpacketizer",
"mpegdashstreamingpacketizer",
"sanjosestreamingpacketizer",
"smoothstreamingpacketizer"
],
"httpRandomizeMediaName": true
},
"dvrConfig": {
"serverName": "_defaultServer_",
"licenseType": "Subscription",
"inUse": false,
"dvrEnable": false,
"windowDuration": 0,
"storageDir": "${com.wowza.wms.context.VHostConfigHome}/dvr",
"archiveStrategy": "append",
"dvrOnlyStreaming": false,
"startRecordingOnStartup": true,
"dvrEncryptionSharedSecret": "",
"dvrMediaCacheEnabled": false,
"httpRandomizeMediaName": false
},
"drmConfig": {
"serverName": "_defaultServer_",
"licenseType": "Subscription",
"inUse": false,
"ezDRMUsername": "",
"ezDRMPassword": "",
"buyDRMUserKey": "",
"buyDRMProtectSmoothStreaming": false,
"buyDRMProtectCupertinoStreaming": false,
"buyDRMProtectMpegDashStreaming": false,
"verimatrixProtectCupertinoStreaming": false,
"verimatrixCupertinoKeyServerIpAddress": "",
"verimatrixCupertinoKeyServerPort": 0,
"verimatrixCupertinoVODPerSessionKeys": false,
"verimatrixProtectSmoothStreaming": false,
"verimatrixSmoothKeyServerIpAddress": "",
"verimatrixSmoothKeyServerPort": 0,
"cupertinoEncryptionAPIBased": false
},
"transcoderConfig": {
"serverName": "_defaultServer_",
"available": true,
"licensed": true,
"licenses": -1,
"licensesInUse": 0,
"templates": {
"vhostName": "_defaultVHost_",
"templates": [
{
"id": "audioonly",
"href": "/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications/livetest/transcoder/templates/audioonly"
},
{
"id": "transcode-h265",
"href": "/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications/livetest/transcoder/templates/transcode-h265"
},
{
"id": "transcode",
"href": "/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications/livetest/transcoder/templates/transcode"
},
{
"id": "transrate",
"href": "/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications/livetest/transcoder/templates/transrate"
}
]
},
"templatesInUse": "${SourceStreamName}.xml,transrate.xml",
"profileDir": "${com.wowza.wms.context.VHostConfigHome}/transcoder/profiles",
"templateDir": "${com.wowza.wms.context.VHostConfigHome}/transcoder/templates",
"createTemplateDir": false
},
"webRTCConfig": {
"serverName": "_defaultServer_",
"enablePublish": false,
"enablePlay": false,
"enableQuery": false,
"iceCandidateIpAddresses": "127.0.0.1,tcp,1935",
"preferredCodecsAudio": "opus,pcmu,pcma",
"preferredCodecsVideo": "vp8,h264",
"debugLog": false
},
"modules": {
"serverName": "_defaultServer_",
"moduleList": [
{
"description": "Base",
"name": "base",
"order": 0,
"class": "com.wowza.wms.module.ModuleCore"
},
{
"description": "Client Logging",
"name": "logging",
"order": 1,
"class": "com.wowza.wms.module.ModuleClientLogging"
},
{
"description": "FLVPlayback",
"name": "flvplayback",
"order": 2,
"class": "com.wowza.wms.module.ModuleFLVPlayback"
},
{
"description": "Core Security Module for Applications",
"name": "ModuleCoreSecurity",
"order": 3,
"class": "com.wowza.wms.security.ModuleCoreSecurity"
},
{
"description": "Schedules streams and playlists.",
"name": "streamPublisher",
"order": 4,
"class": "com.wowza.wms.plugin.streampublisher.ModuleStreamPublisher"
}
]
}
}
作成したApplicationの情報を取得
-
メソッド
-
GET
-
パス
-
/v2/servers/{serverName}/vhosts/{vhostName}/applications/{appName}
-
リクエスト
curl -u "xxxx:yyyy" -X GET -H 'Accept:application/json; charset=utf-8' -H 'Content-Type:application/json; charset=utf-8' http://XXX.XXX.XXX.XXX:8087/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications/livetest
- レスポンス
{"name":"livetest","version":"1613666179000","serverName":"_defaultServer_","appType":"LiveHTTPOrigin","applicationTimeout":0,"pingTimeout":0,"clientStreamReadAccess":"*","clientStreamWriteAccess":"*","avSyncMethod":"senderreport","maxRTCPWaitTime":12000,"httpCORSHeadersEnabled":true,"httpStreamers":["sanjosestreaming","cupertinostreaming","smoothstreaming","mpegdashstreaming"],"mediaReaderRandomAccessReaderClass":"","httpOptimizeFileReads":false,"mediaReaderBufferSeekIO":false,"captionLiveIngestType":"","vodTimedTextProviders":["vodcaptionprovidermp4_3gpp"],"securityConfig":{"serverName":"_defaultServer_","secureTokenVersion":0,"clientStreamWriteAccess":"*","publishRequirePassword":true,"publishPasswordFile":"","publishRTMPSecureURL":"","publishIPBlackList":"","publishIPWhiteList":"","publishBlockDuplicateStreamNames":false,"publishValidEncoders":"","publishAuthenticationMethod":"digest","playMaximumConnections":0,"playRequireSecureConnection":false,"secureTokenSharedSecret":"","secureTokenUseTEAForRTMP":false,"secureTokenIncludeClientIPInHash":false,"secureTokenHashAlgorithm":"","secureTokenQueryParametersPrefix":"","secureTokenOriginSharedSecret":"","playIPBlackList":"","playIPWhiteList":"","playAuthenticationMethod":"none"},"streamConfig":{"serverName":"_defaultServer_","streamType":"live","storageDir":"${com.wowza.wms.context.VHostConfigHome}/content","createStorageDir":false,"storageDirExists":true,"keyDir":"${com.wowza.wms.context.VHostConfigHome}/keys","liveStreamPacketizer":["cupertinostreamingpacketizer","mpegdashstreamingpacketizer","sanjosestreamingpacketizer","smoothstreamingpacketizer"],"httpRandomizeMediaName":true},"dvrConfig":{"serverName":"_defaultServer_","licenseType":"Subscription","inUse":false,"dvrEnable":false,"windowDuration":0,"storageDir":"${com.wowza.wms.context.VHostConfigHome}/dvr","archiveStrategy":"append","dvrOnlyStreaming":false,"startRecordingOnStartup":true,"dvrEncryptionSharedSecret":"","dvrMediaCacheEnabled":false,"httpRandomizeMediaName":false},"drmConfig":{"serverName":"_defaultServer_","licenseType":"Subscription","inUse":false,"ezDRMUsername":"","ezDRMPassword":"","buyDRMUserKey":"","buyDRMProtectSmoothStreaming":false,"buyDRMProtectCupertinoStreaming":false,"buyDRMProtectMpegDashStreaming":false,"verimatrixProtectCupertinoStreaming":false,"verimatrixCupertinoKeyServerIpAddress":"","verimatrixCupertinoKeyServerPort":0,"verimatrixCupertinoVODPerSessionKeys":false,"verimatrixProtectSmoothStreaming":false,"verimatrixSmoothKeyServerIpAddress":"","verimatrixSmoothKeyServerPort":0,"cupertinoEncryptionAPIBased":false},"transcoderConfig":{"serverName":"_defaultServer_","available":true,"licensed":true,"licenses":-1,"licensesInUse":0,"templates":{"vhostName":"_defaultVHost_","templates":[{"id":"audioonly","href":"/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications/livetest/transcoder/templates/audioonly"},{"id":"transcode-h265","href":"/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications/livetest/transcoder/templates/transcode-h265"},{"id":"transcode","href":"/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications/livetest/transcoder/templates/transcode"},{"id":"transrate","href":"/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications/livetest/transcoder/templates/transrate"},{"id":"mnetmulti-4k","href":"/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications/livetest/transcoder/templates/mnetmulti-4k"}]},"templatesInUse":"${SourceStreamName}.xml,transrate.xml","profileDir":"${com.wowza.wms.context.VHostConfigHome}/transcoder/profiles","templateDir":"${com.wowza.wms.context.VHostConfigHome}/transcoder/templates","createTemplateDir":false},"webRTCConfig":{"serverName":"_defaultServer_","enablePublish":false,"enablePlay":false,"enableQuery":false,"iceCandidateIpAddresses":"127.0.0.1,tcp,1935","preferredCodecsAudio":"opus,pcmu,pcma","preferredCodecsVideo":"vp8,h264","debugLog":false},"modules":{"serverName":"_defaultServer_","moduleList":[{"description":"Base","name":"base","order":0,"class":"com.wowza.wms.module.ModuleCore"},{"description":"Client Logging","name":"logging","order":1,"class":"com.wowza.wms.module.ModuleClientLogging"},{"description":"FLVPlayback","name":"flvplayback","order":2,"class":"com.wowza.wms.module.ModuleFLVPlayback"},{"description":"Core Security Module for Applications","name":"ModuleCoreSecurity","order":3,"class":"com.wowza.wms.security.ModuleCoreSecurity"},{"description":"Schedules streams and playlists.","name":"streamPublisher","order":4,"class":"com.wowza.wms.plugin.streampublisher.ModuleStreamPublisher"}]}}
このままだとレスポンスが1行に表示され、情報が多すぎて何が何だかわかりづらいのでいつもはjsonlintで見やすい形に整形させています。jsonlintはJSON構文のチェックにも役立ちます。
$ curl -s -u "xxxx:yyyy" -X GET -H 'Accept:application/json; charset=utf-8' -H 'Content-Type:application/json; charset=utf-8' http://XXX.XXX.XXX.XXX:8087/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications/livetest | jsonlint
■ Mac環境ではbrew install jsonlint
■ npmが使える環境では npm install jsonlint -g
でインストール可能です。
Applicationの情報を更新
-
例ではsmoothstreamingのパケタイザを削除します。
-
メソッド
-
PUT
-
パス
-
/v2/servers/{serverName}/vhosts/{vhostName}/applications/{appName}
-
リクエスト
$ curl -u "xxxx:yyyy" -X PUT -H 'Accept:application/json; charset=utf-8' -H 'Content-Type:application/json; charset=utf-8' http://XXX.XXX.XXX.XXX:8087/v2/servers/_serverName_/vhosts/_defaultVHost_/applications/livetest -d @livetest-update.json
- レスポンス
{"success":true,"message":"Saved","data":null}
{
"name": "livetest",
"version": "",
"serverName": "_defaultServer_",
"appType": "LiveHTTPOrigin",
"maxRTCPWaitTime": 12000,
"httpCORSHeadersEnabled": true,
"streamConfig": {
"serverName": "_defaultServer_",
"streamType": "live",
"storageDir": "${com.wowza.wms.context.VHostConfigHome}/content",
"createStorageDir": false,
"storageDirExists": true,
"keyDir": "${com.wowza.wms.context.VHostConfigHome}/keys",
"liveStreamPacketizer": [
"cupertinostreamingpacketizer",
"mpegdashstreamingpacketizer",
"sanjosestreamingpacketizer"
],
"httpRandomizeMediaName": true
}
}
Applicationに詳細設定を追加
-
例ではHLSのchunkプロパティの設定を有効にし、値を変更します。
- cupertinoChunkDurationTarget
- 6000
-
cupertinoMaxChunkCount
- 20
-
cupertinoPlaylistChunkCount
- 6
-
メソッド
-
PUT
-
パス
-
/v2/servers/{serverName}/vhosts/{vhostName}/applications/{appName}/adv
-
リクエスト:
$ curl -u "xxxx:yyyy" -X PUT -H 'Accept:application/json; charset=utf-8' -H 'Content-Type:application/json; charset=utf-8' http://XXX.XXX.XXX.XXX:8087/v2/servers/_serverName_/vhosts/_defaultVHost_/applications/livetest/adv -d @livetest-adv.json
- レスポンス:
{"success":true,"message":"Saved","data":null}
{
"version": "",
"serverName": "_defaultServer_",
"advancedSettings": [
{
"enabled": true,
"canRemove": true,
"name": "cupertinoChunkDurationTarget",
"value": "6000",
"defaultValue": "10000",
"type": "Integer",
"sectionName": "cupertinostreamingpacketizer",
"section": "/Root/Application/LiveStreamPacketizer",
"documented": true
},
{
"enabled": true,
"canRemove": true,
"name": "cupertinoMaxChunkCount",
"value": "20",
"defaultValue": "10",
"type": "Integer",
"sectionName": "cupertinostreamingpacketizer",
"section": "/Root/Application/LiveStreamPacketizer",
"documented": true
},
{
"enabled": true,
"canRemove": true,
"name": "cupertinoPlaylistChunkCount",
"value": "6",
"defaultValue": "9",
"type": "Integer",
"sectionName": "cupertinostreamingpacketizer",
"section": "/Root/Application/LiveStreamPacketizer",
"documented": true
}
]
}
Applicationの詳細情報を取得
-
メソッド
-
GET
-
パス
-
/v2/servers/{serverName}/vhosts/{vhostName}/applications/{appName}/adv
-
リクエスト
$ curl -s -u "xxxx:yyyy" -X GET -H 'Accept:application/json; charset=utf-8' -H 'Content-Type:application/json; charset=utf-8' http://XXX.XXX.XXX.XXX:8087/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications/livetest/adv |jsonlint
- レスポンス
*設定していない他のプロパティも取得しますのでかなり長い表示になります。
{
"version": "1613667662000",
"serverName": "_defaultServer_",
"advancedSettings": [
{
"enabled": false,
"canRemove": true,
"name": "debugAACTimecodes",
"value": "false",
"defaultValue": "false",
"type": "Boolean",
"sectionName": "cupertinostreamingpacketizer",
"section": "/Root/Application/LiveStreamPacketizer",
"documented": true
},
{
"enabled": false,
"canRemove": true,
"name": "debugMP3Timecodes",
"value": "false",
"defaultValue": "false",
"type": "Boolean",
"sectionName": "cupertinostreamingpacketizer",
"section": "/Root/Application/LiveStreamPacketizer",
"documented": true
},
〜省略〜
Applicationを再起動
Applicationのプロパティ等を追加・更新した場合、Applicationの再起動が必要になります。
-
メソッド
-
PUT
-
パス
-
/v2/servers/{serverName}/vhosts/{vhostName}/applications/{appName}/actions/{action}
-
リクエスト
$ curl -u "xxxx:yyyy" -X PUT -H 'Accept:application/json; charset=utf-8' -H 'Content-Type:application/json; charset=utf-8' http://XXX.XXX.XXX.XXX:8087/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications/livetest/actions/restart
- レスポンス
{"success":true,"message":"Application (livetest) shutdown","data":null}
該当VHost配下に作成されたApplicationをリスト
- メソッド
- GET
- パス
- /v2/servers/{serverName}/vhosts/{vhostName}/applications
- リクエスト
$ curl -s -u "xxxx:yyyy" -X GET -H 'Accept:application/json; charset=utf-8' -H 'Content-Type:application/json; charset=utf-8' http://XXX.XXX.XXX.XXX:8087/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications | jsonlint
- レスポンス
{
"serverName": "_defaultServer_",
"applications": [
{
"id": "live",
"href": "/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications/live",
"appType": "Live",
"dvrEnabled": false,
"drmEnabled": false,
"transcoderEnabled": false,
"streamTargetsEnabled": false
},
{
"id": "livetest",
"href": "/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications/livetest",
"appType": "LiveHTTPOrigin",
"dvrEnabled": false,
"drmEnabled": false,
"transcoderEnabled": false,
"streamTargetsEnabled": false
},
{
"id": "vod",
"href": "/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications/vod",
"appType": "VOD",
"dvrEnabled": false,
"drmEnabled": false,
"transcoderEnabled": false,
"streamTargetsEnabled": false
}
]
}
Applicationを削除
- メソッド
- DELETE
- パス
- /v2/servers/{serverName}/vhosts/{vhostName}/applications/{appName}
- リクエスト
$ curl -u "xxxx:yyyy" -X DELETE -H 'Accept:application/json; charset=utf-8' -H 'Content-Type:application/json; charset=utf-8' http://XXX.XXX.XXX.XXX:8087/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications/livetest
- レスポンス
{"success":true,"message":"Application (livetest) deleted successfully","data":null}
まとめ
如何でしょうか。Applicationの作成だけではなく、Stream Files
やSMIL Files
の作成・削除、Server Statusの取得、Serverチューニングまで簡単に制御できます。API
を活用すればAmazon API Gateway
やAWS Lambda
との連携も可能になり、あらゆる場面で細かいオペレーションまで行うことができます。機会があれば他の設定も紹介していけたらと思います。最後までお読みいただきありがとうございました!
参考文献