要求
- OBS のブラウザソースとして使える
- リアルタイムにサーバー上の情報を取得し、反映する
- その更新の際に、遷移(一回画面が白くなる)を伴わない
実装
というようなものが必要そうだという感じになったので、以下の仕組みにより実現しました。
- JavaScript で、ある更新処理を毎秒走らせ続ける
- 更新処理の中では以下の操作を行う
- 必要な要素をすべて
document.getElementById
で取得する - それらの
INNERHTML
もしくはsrc
を書き換える
- 必要な要素をすべて
このような、JavaScript を用いた非同期通信による遷移なし更新は Ajax(Asynchronous JavaScript + XML) と呼ばれます。世の解説記事にはライブラリを用いたものが多いですが、本記事では必要最小限の JavaScript により実装してみました。
例
実際に作った例はデモにするには複雑過ぎ、かつ更新が高頻度過ぎるので、簡単な例として天気予報を自動更新するブラウザソースを考えます。API の取得には fetch
を用います。
<p>現在時刻(これは内部のデータを参照しています)</p>
<p id="date">date text</p>
<p>今日の気象庁の予報です</p>
<p id="forecast">forecast text</p>
<script>
var url = "https://www.jma.go.jp/bosai/forecast/data/overview_forecast/130000.json";
fetch(url).
then(response => response.json()).
then(data => document.getElementById("forecast").innerHTML = data['text']);
setInterval(function() {
var date = new Date();
document.getElementById("date").innerHTML = date;
var hour = date.getHours();
var minute = date.getMinutes();
if (hour == 0 && minute == 0) {
fetch(url).
then(response => response.json()).then(data => document.getElementById("forecast").innerHTML = data['text']);
}
}, 1000);
</script>
これを開くと(直接 html を開いても、ローカルサーバーとして起動しても、どちらでも構いません)、以下のようになるはずです。
setInterval(hoge,1000)
で更新を毎秒走らせます。
時刻は内部データを取得し、更に 0
時 0
分であった場合は気象庁の API にアクセスし、当日の天気予報を取得します。
これらの更新処理は画面遷移を伴わずに行うことができるため、オーバーレイ素材としてブラウザソースで貼り付けても、他の配信素材を邪魔することなく必要な情報だけを付記することができます。
自分の配信画面に日替わりの天気予報を載せたい人という奇特な人がいたらこれを使ってください。html ファイルを作って上のソースをコピペしたらいけるはずです。
API の整備が必要
今回は気象庁の API を利用させていただきましたが、実際には、自分の Web アプリを利用する、または、他人の Web アプリから API で情報を取得することが多いと思われます。
前者ならば当然、そのための WebAPI、具体的には json を返す仕組みが必要です。
後者にも罠があって、多くの WebAPI は、セキュリティの問題上、オリジンが異なる JavaScript からの直接のリクエストを認めていないようです。
以下のようなエラーが出る場合です。
Access to fetch at 'https://hogehoge' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
この場合のエラー処理
この場合、参考記事で言う「踏み台」となる仕組みが必要です。
上のエラーの要点を日本語に直すと「要求された側に Access-Control-Allow-Origin
っていうヘッダーがない!」というものになります。私の場合は、Django
でローカルサーバーを立てて、同一内容のリクエストを送って、取得した情報をヘッダーつきで返すようにすれば解決しました。
例なので、「全部許可」(*
)にしていますが、本来ならばこれは許可したアプリ等に限定するべきものです。
def api_step(request, param):
url = f'https://api.example.com/{param}'
from django.http import JsonResponse
res = JsonResponse(requests.get(url).json())
res['Access-Control-Allow-Origin'] = '*' # ここが重要
return res