Skip to content

Commit 5ed2ca0

Browse files
committed
OpenH264 E2E テストを追加し、GitHub Actions での自動インストールを設定する
1 parent cba3d13 commit 5ed2ca0

File tree

2 files changed

+258
-0
lines changed

2 files changed

+258
-0
lines changed

.github/workflows/e2e-test.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ jobs:
7070
TEST_SIGNALING_URL: ${{ secrets.TEST_SIGNALING_URL }}
7171
TEST_CHANNEL_ID_PREFIX: ${{ secrets.TEST_CHANNEL_ID_PREFIX }}
7272
TEST_SECRET_KEY: ${{ secrets.TEST_SECRET_KEY }}
73+
OPENH264_VERSION: 2.6.0
7374
steps:
7475
- uses: actions/checkout@v5
7576

@@ -114,6 +115,21 @@ jobs:
114115
fi
115116
done
116117
118+
# OpenH264 のダウンロード (GitHub-hosted ランナーのみ)
119+
- name: Download OpenH264
120+
if: ${{ runner.environment != 'self-hosted' }}
121+
uses: shiguredo/github-actions/.github/actions/download-openh264@main
122+
id: openh264
123+
with:
124+
platform_name: ${{ matrix.platform.platform-name }}
125+
openh264_version: ${{ env.OPENH264_VERSION }}
126+
use-cache: true
127+
128+
# OpenH264 環境変数の設定 (GitHub-hosted ランナーのみ)
129+
- name: Setup OpenH264 environment
130+
if: ${{ runner.environment != 'self-hosted' && steps.openh264.outputs.openh264_path }}
131+
run: echo "OPENH264_PATH=${{ steps.openh264.outputs.openh264_path }}" >> $GITHUB_ENV
132+
117133
# self-hosted runner の場合このダウンロードが凄く時間かかる
118134
- name: Download and setup sumomo binary
119135
uses: ./.github/actions/download-sumomo

e2e-test/test_sumomo_openh264.py

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
"""OpenH264 を使用した Sumomo の E2E テスト"""
2+
3+
import os
4+
import time
5+
6+
import pytest
7+
8+
from helper import get_codec, get_outbound_rtp, get_simulcast_outbound_rtp
9+
from sumomo import Sumomo
10+
11+
# OpenH264 を使用するテストは OPENH264_PATH が設定されていない場合スキップ
12+
pytestmark = [
13+
pytest.mark.skipif(
14+
not os.environ.get("OPENH264_PATH"),
15+
reason="OPENH264_PATH not set in environment",
16+
),
17+
]
18+
19+
20+
def test_sumomo_sendonly_with_openh264_encoder(sora_settings, free_port):
21+
"""sendonly モードで OpenH264 を使用した H.264 エンコーダーが動作することを確認"""
22+
23+
openh264_path = os.environ.get("OPENH264_PATH")
24+
25+
with Sumomo(
26+
signaling_url=sora_settings.signaling_url,
27+
channel_id=sora_settings.channel_id,
28+
role="sendonly",
29+
metadata=sora_settings.metadata,
30+
http_port=free_port,
31+
audio=True,
32+
video=True,
33+
audio_codec_type="OPUS",
34+
video_codec_type="H264",
35+
h264_encoder="cisco_openh264", # OpenH264 エンコーダーを使用
36+
openh264=openh264_path, # 明示的にパスを指定
37+
) as s:
38+
time.sleep(3)
39+
40+
stats = s.get_stats()
41+
assert stats is not None
42+
assert isinstance(stats, list)
43+
assert len(stats) > 0
44+
45+
# H.264 codec が存在することを確認
46+
h264_codec = get_codec(stats, "video/H264")
47+
assert h264_codec is not None, "H.264 codec not found in stats"
48+
assert h264_codec["mimeType"] == "video/H264"
49+
assert h264_codec["clockRate"] == 90000
50+
51+
# video の outbound-rtp で OpenH264 が使用されていることを確認
52+
video_outbound = get_outbound_rtp(stats, "video")
53+
assert video_outbound is not None, "Video outbound-rtp not found"
54+
assert "encoderImplementation" in video_outbound
55+
assert (
56+
"OpenH264" in video_outbound["encoderImplementation"]
57+
), f"Expected OpenH264 encoder, but got {video_outbound.get('encoderImplementation')}"
58+
59+
# OpenH264 エンコーダーの統計情報を検証
60+
assert video_outbound["codecId"] == h264_codec["id"]
61+
assert "ssrc" in video_outbound
62+
assert "packetsSent" in video_outbound
63+
assert "bytesSent" in video_outbound
64+
assert "framesEncoded" in video_outbound
65+
assert video_outbound["packetsSent"] > 0
66+
assert video_outbound["bytesSent"] > 0
67+
assert video_outbound["framesEncoded"] > 0
68+
69+
70+
def test_sumomo_sendrecv_with_openh264_encoder(sora_settings, port_allocator):
71+
"""sendrecv モードで OpenH264 を使用した H.264 エンコーダーが動作することを確認"""
72+
73+
openh264_path = os.environ.get("OPENH264_PATH")
74+
75+
with Sumomo(
76+
signaling_url=sora_settings.signaling_url,
77+
channel_id=sora_settings.channel_id,
78+
role="sendrecv",
79+
metadata=sora_settings.metadata,
80+
http_port=next(port_allocator),
81+
audio=True,
82+
video=True,
83+
audio_codec_type="OPUS",
84+
video_codec_type="H264",
85+
h264_encoder="cisco_openh264",
86+
openh264=openh264_path,
87+
) as s1:
88+
with Sumomo(
89+
signaling_url=sora_settings.signaling_url,
90+
channel_id=sora_settings.channel_id,
91+
role="sendrecv",
92+
metadata=sora_settings.metadata,
93+
http_port=next(port_allocator),
94+
audio=True,
95+
video=True,
96+
) as s2:
97+
time.sleep(3)
98+
99+
# Client1 の統計情報を確認
100+
stats1 = s1.get_stats()
101+
assert stats1 is not None
102+
103+
# OpenH264 エンコーダーが使用されていることを確認
104+
video_outbound1 = get_outbound_rtp(stats1, "video")
105+
assert video_outbound1 is not None
106+
assert "OpenH264" in video_outbound1["encoderImplementation"]
107+
assert video_outbound1["packetsSent"] > 0
108+
assert video_outbound1["bytesSent"] > 0
109+
110+
# Client2 の統計情報を確認
111+
stats2 = s2.get_stats()
112+
assert stats2 is not None
113+
114+
# Client2 も正常に送受信できていることを確認
115+
video_outbound2 = get_outbound_rtp(stats2, "video")
116+
assert video_outbound2 is not None
117+
assert video_outbound2["packetsSent"] > 0
118+
assert video_outbound2["bytesSent"] > 0
119+
120+
121+
def test_sumomo_openh264_with_simulcast(sora_settings, free_port):
122+
"""OpenH264 を使用したサイマルキャストの動作を確認"""
123+
124+
openh264_path = os.environ.get("OPENH264_PATH")
125+
126+
with Sumomo(
127+
signaling_url=sora_settings.signaling_url,
128+
channel_id=sora_settings.channel_id,
129+
role="sendonly",
130+
metadata=sora_settings.metadata,
131+
http_port=free_port,
132+
audio=True,
133+
video=True,
134+
audio_codec_type="OPUS",
135+
video_codec_type="H264",
136+
video_bit_rate=3000,
137+
h264_encoder="cisco_openh264",
138+
openh264=openh264_path,
139+
simulcast=True,
140+
resolution="960x540",
141+
) as s:
142+
time.sleep(10)
143+
144+
stats = s.get_stats()
145+
assert stats is not None
146+
147+
# サイマルキャストで複数の rid が存在することを確認
148+
video_outbound_by_rid = get_simulcast_outbound_rtp(stats, "video")
149+
assert len(video_outbound_by_rid) == 3, (
150+
f"Expected 3 simulcast streams with OpenH264, but got {len(video_outbound_by_rid)}"
151+
)
152+
153+
# 全ての rid が存在することを確認
154+
assert set(video_outbound_by_rid.keys()) == {
155+
"r0",
156+
"r1",
157+
"r2",
158+
}, f"Expected rid r0, r1, r2, but got {set(video_outbound_by_rid.keys())}"
159+
160+
# r0 (低解像度) の検証
161+
outbound_rtp_r0 = video_outbound_by_rid["r0"]
162+
assert "encoderImplementation" in outbound_rtp_r0
163+
# OpenH264 では SimulcastEncoderAdapter と OpenH264 の組み合わせ
164+
assert "SimulcastEncoderAdapter" in outbound_rtp_r0["encoderImplementation"]
165+
assert "OpenH264" in outbound_rtp_r0["encoderImplementation"]
166+
assert outbound_rtp_r0["rid"] == "r0"
167+
assert "ssrc" in outbound_rtp_r0
168+
assert "packetsSent" in outbound_rtp_r0
169+
assert "bytesSent" in outbound_rtp_r0
170+
assert "frameWidth" in outbound_rtp_r0
171+
assert "frameHeight" in outbound_rtp_r0
172+
assert outbound_rtp_r0["packetsSent"] > 0
173+
assert outbound_rtp_r0["bytesSent"] > 0
174+
assert outbound_rtp_r0["frameWidth"] == 240
175+
assert outbound_rtp_r0["frameHeight"] == 128
176+
print(f"r0: {outbound_rtp_r0['frameWidth']}x{outbound_rtp_r0['frameHeight']}")
177+
178+
# r1 (中解像度) の検証
179+
outbound_rtp_r1 = video_outbound_by_rid["r1"]
180+
assert "encoderImplementation" in outbound_rtp_r1
181+
assert "SimulcastEncoderAdapter" in outbound_rtp_r1["encoderImplementation"]
182+
assert "OpenH264" in outbound_rtp_r1["encoderImplementation"]
183+
assert outbound_rtp_r1["rid"] == "r1"
184+
assert "ssrc" in outbound_rtp_r1
185+
assert "packetsSent" in outbound_rtp_r1
186+
assert "bytesSent" in outbound_rtp_r1
187+
assert "frameWidth" in outbound_rtp_r1
188+
assert "frameHeight" in outbound_rtp_r1
189+
assert outbound_rtp_r1["packetsSent"] > 0
190+
assert outbound_rtp_r1["bytesSent"] > 0
191+
assert outbound_rtp_r1["frameWidth"] == 480
192+
assert outbound_rtp_r1["frameHeight"] == 256
193+
print(f"r1: {outbound_rtp_r1['frameWidth']}x{outbound_rtp_r1['frameHeight']}")
194+
195+
# r2 (高解像度) の検証
196+
outbound_rtp_r2 = video_outbound_by_rid["r2"]
197+
assert "encoderImplementation" in outbound_rtp_r2
198+
assert "SimulcastEncoderAdapter" in outbound_rtp_r2["encoderImplementation"]
199+
assert "OpenH264" in outbound_rtp_r2["encoderImplementation"]
200+
assert outbound_rtp_r2["rid"] == "r2"
201+
assert "ssrc" in outbound_rtp_r2
202+
assert "packetsSent" in outbound_rtp_r2
203+
assert "bytesSent" in outbound_rtp_r2
204+
assert "frameWidth" in outbound_rtp_r2
205+
assert "frameHeight" in outbound_rtp_r2
206+
assert outbound_rtp_r2["packetsSent"] > 0
207+
assert outbound_rtp_r2["bytesSent"] > 0
208+
assert outbound_rtp_r2["frameWidth"] == 960
209+
assert outbound_rtp_r2["frameHeight"] == 528
210+
print(f"r2: {outbound_rtp_r2['frameWidth']}x{outbound_rtp_r2['frameHeight']}")
211+
212+
213+
def test_sumomo_explicit_openh264_path(sora_settings, free_port):
214+
"""明示的に OpenH264 パスを指定した場合の動作を確認"""
215+
216+
openh264_path = os.environ.get("OPENH264_PATH")
217+
218+
with Sumomo(
219+
signaling_url=sora_settings.signaling_url,
220+
channel_id=sora_settings.channel_id,
221+
role="sendonly",
222+
metadata=sora_settings.metadata,
223+
http_port=free_port,
224+
audio=True,
225+
video=True,
226+
audio_codec_type="OPUS",
227+
video_codec_type="H264",
228+
h264_encoder="cisco_openh264",
229+
openh264=openh264_path, # 明示的にパスを指定
230+
) as s:
231+
time.sleep(3)
232+
233+
stats = s.get_stats()
234+
assert stats is not None
235+
236+
# OpenH264 エンコーダーが使用されていることを確認
237+
video_outbound = get_outbound_rtp(stats, "video")
238+
assert video_outbound is not None
239+
assert "encoderImplementation" in video_outbound
240+
assert (
241+
"OpenH264" in video_outbound["encoderImplementation"]
242+
), "OpenH264 encoder not found with explicit path"

0 commit comments

Comments
 (0)