![見出し画像](https://assets.st-note.com/production/uploads/images/146328148/rectangle_large_type_2_6f0c0fd27ace53502cff44201ebab3d2.jpeg?width=1200)
Sony製カメラから無線で映像を取り出す - Containerに詰めたこの想いを
こんにちは、音楽技術部技術班のDDliaです。
現在サークルではカメラを所有しており、カメラ映像をHDMI経由でキャプチャーボードでPCに取り込んで、それをNDIで各種PCに送信しています。これは最小限の遅延(600ミリ秒程度)で伝送できるのですが、いちいちPC起動してケーブルをいろいろ挿して… とやるのは面倒なのでどうにかカメラから直接無線で映像を飛ばせるようにします。
カメラについて
使っているカメラはSony製のHDR-CX680というものです。部室に2台あります。Wi-Fi接続をサポートしており、ライブストリーミングも可能ですが……
Ustream(現 IBM Video Streaming)への配信しか対応していない!!
で、そのIBM Video Streamingはいくらかかるかというと…
![](https://assets.st-note.com/img/1720196360678-XH0FGipnq1.png?width=1200)
一番安いプランで ¥21900/月 ですね。富豪じゃないのでさすがに出せない。
探してみる
私は富豪ではないので、どうにかならないか探してみるとGitHubでissueが開かれていました。
Sony製カメラでuStream以外へストリーミングするにはどうすればよいのかが議論されています。目を通してみると、
DNSスプーフィングで api.ustream.tv をLAN内のサーバに向ける
カメラがhttp://api.ustream.tv/users/self/channels.json から接続先情報を読み取るので、そこに配信先アドレスを記述する
配信サーバからカメラに対して定期的にpingを送る(AMFメッセージを偽装)
カメラに配信用資格情報を書き込む
あたりをやればよさそう。
テスト
RTMPサーバを建てる
まずは配信用のRTMPサーバを建てます。
docker-composeで簡単に立ち上げれるようにしているので、適当なLinuxサーバで立ち上げます。
$ sudo dnf update -y && sudo dnf install -y git podman podman-compose podman-docker
$ git clone https://github.com/TechnoTUT/rtmp-live-server.git
$ cd rtmp-live-server
$ podman-compose up -d
DNSスプーフィングで api.ustream.tv をLAN内のサーバに向ける
テスト環境ではNEC IX3110というルータを使っていて、DNSレコードを登録できる機能があるのでそれを使います。
dns host api.ustream.tv <カメラから映像を受け取るサーバのIPアドレス>
カメラから映像を受け取るRTMPサーバを建てる
先ほどのRTMPサーバとは別にカメラから映像を受け取るRTMPサーバを建てます。その辺に転がっているLinuxマシンを拾ってきましょう。配信サーバからカメラに対して定期的にpingを送る(AMFメッセージを偽装)必要があるので、nginxを自分でビルドします。
nginx-rtmp-moduleは以下を使います。
(https://github.com/transelement/nginx-rtmp-module だと自分の環境下ではビルドエラーが出たので修正してあります。)
$ sudo apt update -y && sudo apt install -y nginx git wget tar build-essential libperl-dev libgeoip-dev libgd-dev libpcre3 libpcre3-dev libxml2 libxslt1-dev libxslt1.1 libxslt1-dev
$ wget https://nginx.org/download/nginx-1.22.1.tar.gz && tar xzf nginx-1.22.1.tar.gz && rm -f nginx-1.22.1.tar.gz
$ wget https://www.openssl.org/source/openssl-3.3.1.tar.gz && tar xzf openssl-3.3.1.tar.gz && rm -f openssl-3.3.1.tar.gz
$ git clone https://github.com/TechnoTUT/nginx-rtmp-module.git
$ cd nginx-1.22.1
$ ./configure --with-cc-opt='-g -O2 -ffile-prefix-map=/build/nginx-AoTv4W/nginx-1.22.1=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' \
--with-ld-opt='-Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=stderr \
--lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi \
--http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-compat --with-debug --with-pcre-jit --with-http_ssl_module \
--with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads \
--with-http_addition_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_secure_link_module \
--with-http_sub_module --with-mail_ssl_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-stream_realip_module --with-http_geoip_module=dynamic --with-http_image_filter_module=dynamic \
--with-http_perl_module=dynamic --with-http_xslt_module=dynamic --with-mail=dynamic --with-stream=dynamic --with-stream_geoip_module=dynamic \
--add-dynamic-module=~/nginx-rtmp-module --with-openssl=~/openssl-3.3.1
$ make modules
$ mkdir -p /usr/lib/nginx/modules && cp ~/nginx-1.22.1/objs/*.so /usr/lib/nginx/modules
$ mkdir -p /var/www/ustream/users/self && chown -R www-data:www-data /var/www/ustream
ビルドしたら、/var/www/ustream/users/selfに以下の内容でchannels.jsonを配置します。
{
"channels": {
"12345678": {
"broadcast_urls": [
"rtmp://api.ustream.tv/mystream"
]
}
}
}
/etc/nginx/nginx.conf を以下に書き換えます。
user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
load_module /usr/lib/nginx/modules/ngx_rtmp_module.so;
events {
worker_connections 768;
# multi_accept on;
}
rtmp {
access_log /var/log/nginx/ustream-rtmp-access.log;
server {
listen 1935;
chunk_size 4096;
max_message 5M;
ping 20s;
ping_timeout 36000s;
force_ping on;
application mystream {
live on;
meta off;
push <配信用RTMPサーバのURL>;
# Reduce buffer size
wait_key on;
sync 10ms;
drop_idle_publisher 5s;
}
}
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
##
# Gzip Settings
##
gzip on;
server {
listen 80;
server_name api.ustream.tv;
error_log /var/log/nginx/ustream-error.log;
access_log /var/log/nginx/ustream-access.log;
location / {
root /var/www/ustream/;
}
location /stat {
rtmp_stat all;
}
}
}
各種設定が済んだら、nginxを起動して配信サーバを起動します。
$ systemctl enable --now nginx
カメラに配信用資格情報を書き込む
以下のSony-PMCA-REを使用して、書き込みを行います。
Releaseから pmca-console.exe をダウンロードします。
pmca-console.exeと同じディレクトリに以下の内容でstream.cfgを作成します。
[
[
"twitterEnabled",
0
],
[
"twitterConsumerKey",
""
],
[
"twitterConsumerSecret",
""
],
[
"twitterAccessToken1",
""
],
[
"twitterAccessTokenSecret",
""
],
[
"twitterMessage",
"Live Streaming from Handycam by Sony"
],
[
"facebookEnabled",
0
],
[
"facebookAccessToken",
""
],
[
"facebookMessage",
"Live Streaming from Handycam by Sony"
],
[
"service",
0
],
[
"enabled",
1
],
[
"macId",
"1234567890123456789012345678901234567890"
],
[
"macSecret",
"123456789012345678901234567890123467890"
],
[
"macIssueTime",
"a9315a5f00000000"
],
[
"unknown",
1
],
[
"channels",
[
12345678
]
],
[
"shortURL",
"http://ustre.am/1AAAA"
],
[
"videoFormat",
3
],
[
"supportedFormats",
[
1,
3
]
],
[
"enableRecordMode",
0
],
[
"videoTitle",
"Test"
],
[
"videoDescription",
"Test"
],
[
"videoTag",
"Test"
]
]
カメラをMTPモードで接続し、PCで書き込みます。
> pmca-console-v0.18-win.exe stream -w stream.cfg
動作確認
カメラをライブストリーミングモードに変更して、ストリームを開始します。
Sony製カメラからustreamとは別のRTMPサーバに打ち上げるやつできた pic.twitter.com/CrbrExfTWm
— DDlia (@ddLi907) July 2, 2024
うまく動いたっぽい。
部室にデプロイ
テストはうまく行ったので、これを部室やコモンズイベントでも使えるようにしておきます。テスト環境と同じ手順で構築すれば動くわけですが、実際にはカメラが2台分あり、台数分のサーバ構築をするのは面倒です。
コンテナイメージを錬成して、部室のKubernetes環境に環境変数だけ変えてデプロイします。コンテナは神。
コンテナに想いを詰める
Dockerfileを書いて、それをビルドして ghcr.io で公開します。
https://ghcr.io/TechnoTUT/sonycam-nginx からpullできます。
マニフェストを書く
Kubernetesに載せるために、まずはマニフェストを書きます。
カメラから映像を受け取るnginxサーバは、先程錬成した ghcr.io/technotut/sonycam-nginx を使用し、api.ustream.tvをローカルIPで返すDNSサーバはCoreDNSを使っています。マニフェストは以下のように書いています。
apiVersion: apps/v1
kind: Deployment
metadata:
name: cam1-nginx-deployment
labels:
app: cam1-sonycam-nginx
namespace: cam1
spec:
selector:
matchLabels:
app: cam1-sonycam-nginx
replicas: 1
template:
metadata:
labels:
app: cam1-sonycam-nginx
spec:
containers:
- name: cam1-sonycam-nginx
image: ghcr.io/technotut/sonycam-nginx:main
env:
- name: SERVER_URL
value: rtmp://rtmp-service.live.svc.cluster.local:1935/live/cam1
ports:
- containerPort: 1935
- containerPort: 80
resources:
limits:
cpu: 1
memory: 256Mi
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: cam1-nginx-service
labels:
app: cam1-sonycam-nginx
namespace: cam1
annotations:
external-dns.alpha.kubernetes.io/hostname: cam1.kube.technotut.net
spec:
selector:
app: cam1-sonycam-nginx
type: LoadBalancer
loadBalancerIP: 10.33.71.1
ports:
- name: rtmp
protocol: TCP
port: 1935
targetPort: 1935
- name: http
protocol: TCP
port: 80
targetPort: 80
envで配信サーバのURLを指定し、metadata.annotationsでホスト名を外部のDNSサーバに登録して cam1.kube.technotut.net でアクセスできるようにしています。
ついでに、配信用RTMPサーバ用のマニフェストも作っておきます。
apiVersion: apps/v1
kind: Deployment
metadata:
name: rtmp-deployment
labels:
app: rtmp-live-server
namespace: live
spec:
selector:
matchLabels:
app: rtmp-live-server
replicas: 1
template:
metadata:
labels:
app: rtmp-live-server
spec:
containers:
- name: rtmp-live-server
image: ghcr.io/technotut/rtmp-live-server:main
ports:
- containerPort: 1935
- containerPort: 8080
resources:
limits:
cpu: 1
memory: 256Mi
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: rtmp-service
labels:
app: rtmp-live-server
namespace: live
annotations:
external-dns.alpha.kubernetes.io/hostname: live.kube.technotut.net
spec:
selector:
app: rtmp-live-server
type: LoadBalancer
loadBalancerIP: 10.33.0.1
ports:
- name: rtmp
protocol: TCP
port: 1935
targetPort: 1935
- name: http
protocol: TCP
port: 80
targetPort: 8080
ArgoCDに登録
ArgoCDでマニフェストを適用します。
ここで紹介した手順で操作します。
argocd login kube.intra.technotut.net:30001
kubectl create namespace cam1
argocd app create cam1 --repo https://github.com/TechnoTUT/k3s.git --path manifest/cam1 --dest-server https://kubernetes.default.svc --dest-namespace cam1
argocd app sync cam1
argocd app set cam1 --sync-policy automated
Wwb UIで確認してみると、ちゃんと動いていることが確認できますね。
まえからだいぶふえた pic.twitter.com/F42kFfXDkI
— DDlia (@ddLi907) July 4, 2024
動作確認
部室のKubernetesクラスタで動いた https://t.co/ItUebxlJ07 pic.twitter.com/qL8gi0z4YY
— DDlia (@ddLi907) July 4, 2024
綺麗に動いててくれてそう👍 pic.twitter.com/gaFkvldHCo
— DDlia (@ddLi907) July 5, 2024
使い方
OBSのメディアストリームなり、VLCなりで
rtmp://live.kube.technotut.net/live/cam1
rtmp://live.kube.technotut.net/live/cam2
を開くと映像を受信できます!
きりしゃめくん3カメで撮ってる pic.twitter.com/xZepVRo4aj
— DDlia (@ddLi907) July 5, 2024
まとめ
というわけで、部室のカメラから直接PCに映像を飛ばせるようにしました。今後のイベント等で活用してもらえると嬉しいです。
また、部室にKubernetesの環境を用意してあるので、ぜひみなさんも部内に提供したいサービスを気軽にコンテナに詰めて動かしに来てください。
この記事が気に入ったらサポートをしてみませんか?