Skip to content

Commit 6196cc7

Browse files
committed
Merge branch 'release/2025.3.0'
2 parents 6728110 + 34247e8 commit 6196cc7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+3396
-2428
lines changed

.github/dependabot.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "github-actions"
4+
directory: "/"
5+
schedule:
6+
interval: "weekly"
7+
allow:
8+
- dependency-name: "actions/checkout"
9+
- dependency-name: "actions/setup-java"
10+
- dependency-name: "rtCamp/action-slack-notify"
11+
- dependency-name: "anthropics/claude-code-action"
12+
- dependency-name: "shiguredo/github-actions"

.github/workflows/build.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,16 @@ on:
66
paths-ignore:
77
- 'README.md'
88
- 'CHANGES.md'
9+
- 'CLAUDE.md'
910
- 'LICENSE'
1011
- 'THANKS'
12+
- '.github/workflows/claude.yml'
13+
- '.github/copilot-instructions.md'
14+
- 'sora-android-sdk/packages.md'
15+
- 'docs/**'
16+
- 'jitpack.yml'
17+
- 'canary.py'
18+
- '.gitignore'
1119

1220
jobs:
1321
build:
@@ -17,7 +25,7 @@ jobs:
1725
steps:
1826
- uses: actions/checkout@v5
1927
- name: Set up JDK
20-
uses: actions/setup-java@v4
28+
uses: actions/setup-java@v5
2129
with:
2230
distribution: 'temurin'
2331
# java-version を 17 にしている理由は以下です

.github/workflows/claude.yml

Lines changed: 8 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -13,48 +13,17 @@ permissions:
1313
actions: read
1414

1515
env:
16-
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY_SORA_OSS_SONNET }}
16+
CLAUDE_API_KEY: ${{ secrets.ANTHROPIC_API_KEY_SORA_OSS_SONNET }}
17+
CLAUDE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN_VOLUNTAS }}
1718

1819
jobs:
19-
claude-opus-response-voluntas:
20-
if: github.event.comment.user.login == 'voluntas'
20+
claude-response:
2121
runs-on: ubuntu-24.04
22-
timeout-minutes: 20
22+
timeout-minutes: 15
2323
steps:
2424
- uses: actions/checkout@v5
25-
- uses: anthropics/claude-code-action@beta
25+
- uses: shiguredo/github-actions/.github/actions/claude-code-action@main
2626
with:
27-
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN_VOLUNTAS }}
28-
github_token: ${{ secrets.GITHUB_TOKEN }}
29-
model: "claude-opus-4-20250514"
30-
trigger_phrase: "!opus"
31-
timeout_minutes: 15
32-
disallowed_tools: "Bash(git:*)"
33-
34-
check-permission:
35-
if: github.event.comment.user.login != 'voluntas'
36-
runs-on: ubuntu-24.04
37-
outputs:
38-
has_permission: ${{ steps.check.outputs.has-permission }}
39-
steps:
40-
- uses: actions/checkout@v5
41-
- id: check
42-
uses: shiguredo/github-actions/.github/actions/check-write-permission@main
43-
with:
44-
username: ${{ github.event.comment.user.login }}
45-
46-
claude-sonnet-response-others:
47-
needs: check-permission
48-
if: needs.check-permission.outputs.has_permission == 'true'
49-
runs-on: ubuntu-24.04
50-
timeout-minutes: 20
51-
steps:
52-
- uses: actions/checkout@v5
53-
- uses: anthropics/claude-code-action@beta
54-
with:
55-
anthropic_api_key: ${{ env.ANTHROPIC_API_KEY }}
56-
github_token: ${{ secrets.GITHUB_TOKEN }}
57-
model: "claude-sonnet-4-20250514"
58-
trigger_phrase: "!sonnet"
59-
timeout_minutes: 15
60-
disallowed_tools: "Bash(git:*)"
27+
api_key: ${{ env.CLAUDE_API_KEY }}
28+
oauth_user: voluntas
29+
oauth_token: ${{ env.CLAUDE_OAUTH_TOKEN }}

CHANGES.md

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,66 @@
1111

1212
## develop
1313

14+
## 2025.3.0
15+
16+
**リリース日**: 2025-11-11
17+
18+
- [UPDATE] libwebrtc を 142.7444.2.1 に上げる
19+
- @t-miya @zztkm
20+
- [UPDATE] Kotlin バージョンを 2.0.20 に上げる
21+
- @t-miya
22+
- [ADD] マイク録音の一時停止/再開機能を追加する
23+
- 配信中に AudioDeviceModule の録音を停止することで、Android 実機のマイクインジケータを消灯させることを可能にする
24+
- AudioDeviceModuleWrapper クラスを追加する
25+
- JavaAudioDeviceModule を対象とした録音停止/再開のラッパークラス
26+
- 専用の HandlerThread 上で suspend 関数として pauseRecording() / resumeRecording() を提供する
27+
- アプリ側でカスタム ADM を差し込む場合は AudioDeviceModuleWrapper は利用されない
28+
- SoraMediaChannel に以下のメソッドを追加する
29+
- suspend fun setAudioRecordingPaused(paused: Boolean): Boolean
30+
- 録音の一時停止/再開を非同期で実行する
31+
- 内部では PeerChannel 経由で AudioDeviceModuleWrapper の pauseRecording()/resumeRecording() が呼ばれる
32+
- AudioDeviceModule の制御に加え、ローカル AudioTrack の無効化/有効化も併せて行う
33+
- fun isAudioRecordingPaused(): Boolean
34+
- 現在の録音停止状態を返す
35+
- @t-miya
36+
- [ADD] AudioTrack から音声データを受け取るためのコールバックインターフェースである AudioTrackSink を追加する
37+
- この機能を利用すると AudioTrack ごとにコールバックから音声データを取得できる
38+
- @zztkm
39+
- [ADD] AudioTrack に AudioTrackSink と関連付けるためのメソッドを追加する
40+
- addSink
41+
- AudioTrack と AudioTrackSink を関連付けるためのメソッド
42+
- removeSink
43+
- AudioTrack と AudioTrackSink の関連付けを解除するためのメソッド
44+
- @zztkm
45+
46+
### misc
47+
48+
- [UPDATE] ktlint バージョンを上げる
49+
- ktlint を 1.7.1 に上げる
50+
- ktlint-gradle を 13.1.0 に上げる
51+
- @t-miya
52+
- [UPDATE] Android Gradle Plugin バージョンを 8.11.1 に上げる
53+
- @t-miya
54+
- [UPDATE] grgit が git worktree のディレクトリでは使えないことが判明したため、`BuildConfig.REVISION` を取得する方法を grgit から git コマンドに移行する
55+
- Sora Android SDK ではコミットハッシュを取得するためだけに Grgit を利用しており、git コマンドの利用で十分であると判断した
56+
- @zztkm
57+
- [UPDATE] build.yml の実行除外対象を追加する
58+
- paths-ignore に以下を追加
59+
- 'CLAUDE.md'
60+
- '.github/workflows/claude.yml'
61+
- '.github/copilot-instructions.md'
62+
- 'sora-android-sdk/packages.md'
63+
- 'docs/**'
64+
- 'jitpack.yml'
65+
- 'canary.py'
66+
- '.gitignore'
67+
- [UPDATE] canary.py の SDKInfo.kt の `version` 変数名を `VERSION` に変更する
68+
- ktlint バージョンアップにより命名規則のチェックが厳格になった
69+
- @zztkm
70+
- [UPDATE] システム条件を更新する
71+
- Android Studio 2025.2.1 以降
72+
- @zztkm
73+
1474
## 2025.2.0
1575

1676
**リリース日**: 2025-09-17
@@ -99,7 +159,7 @@
99159
- @zztkm
100160
- [ADD] `SoraMediaOption``DegradationPreference` を追加
101161
- クライアント側の状況により設定した解像度やフレームレートを維持できなくなった場合にどのように質を下げるか制御できるパラメータとして `SoraMediaOption.degradationPreference` を追加した
102-
- `degradationPreference` の設定は必須ではなく、未指定の場合は libwebrtc デフォルトの挙動として `BALANCED` が適用される
162+
- `degradationPreference` の設定は必須ではなく、未指定の場合は libwebrtc デフォルトの挙動として `MAINTAIN_FRAMERATE` が適用される
103163
- @t-miya
104164
- [ADD] サイマルキャストの映像のエンコーディングパラメーター `scaleResolutionDownTo` を追加する
105165
- @zztkm
@@ -109,14 +169,19 @@
109169
- サイマルキャスト有効時も SW のみ構成に切り替える
110170
- `videoEncoderFactory` を明示設定している場合は本オプションは無視される
111171
- @zztkm
112-
113172
- [FIX] `SoraMediaChannel.internalDisconnect` での `SoraMediaChannel.Listener.onClose` の呼び出しタイミングを切断処理がすべて完了したあとに修正する
114173
- 切断処理が終了する前に `onClose` を呼び出していたため、切断処理が完了してから呼び出すように修正
115174
- `contactSignalingEndpoint``connectedSignalingEndpoint` は onClose で参照される可能性があるため、onClose 実行よりあとに null になるように onClose に合わせて処理順を変更
116175
- @zztkm
117176

118177
### misc
119178

179+
- [CHANGE] Gradle を Kotlin DSL 移行する
180+
- build.gradle、settings.gradle、sora-android-sdk/build.gradle それぞれを Kotlin DSL(.kts) に移行
181+
- @t-miya
182+
- [CHANGE] 依存ライブラリバージョンの管理をバージョンカタログに移行する
183+
- gradle/libs.versions.toml を追加
184+
- @t-miya
120185
- [UPDATE] actions/checkout@v4 を actions/checkout@v5 に上げる
121186
- @torikizi
122187

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Sora Android SDK
22

33
[![Release](https://jitpack.io/v/shiguredo/sora-android-sdk.svg)](https://jitpack.io/#shiguredo/sora-android-sdk)
4-
[![libwebrtc](https://img.shields.io/badge/libwebrtc-138.7204-blue.svg)](https://chromium.googlesource.com/external/webrtc/+/branch-heads/7204)
4+
[![libwebrtc](https://img.shields.io/badge/libwebrtc-142.7444-blue.svg)](https://chromium.googlesource.com/external/webrtc/+/branch-heads/7444)
55
[![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/shiguredo/sora-android-sdk.svg)](https://github.com/shiguredo/sora-android-sdk.svg)
66
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
77

@@ -21,7 +21,7 @@ Please read https://github.com/shiguredo/oss before use.
2121
## システム条件
2222

2323
- Android 5 以降 (エミュレーターでの動作は保証しません)
24-
- Android Studio 2025.1.1 以降
24+
- Android Studio 2025.2.1 以降
2525
- WebRTC SFU Sora 2025.1.0 以降
2626

2727
## サンプル

build.gradle

Lines changed: 0 additions & 52 deletions
This file was deleted.

build.gradle.kts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
plugins {
2+
alias(libs.plugins.versions)
3+
alias(libs.plugins.dokka)
4+
alias(libs.plugins.android.application) apply false
5+
alias(libs.plugins.android.library) apply false
6+
alias(libs.plugins.kotlin.android) apply false
7+
alias(libs.plugins.android.maven) apply false
8+
alias(libs.plugins.ktlint) apply false
9+
}
10+
11+
allprojects {
12+
repositories {
13+
google()
14+
mavenCentral()
15+
maven("https://jitpack.io")
16+
}
17+
}
18+
19+
tasks.register<Delete>("clean") {
20+
delete(rootProject.layout.buildDirectory)
21+
}
22+
23+
// 不安定バージョンを除外する設定
24+
fun isNonStable(version: String): Boolean {
25+
val qualifiers = listOf("alpha", "beta", "rc", "M")
26+
return qualifiers.any { qualifier ->
27+
version.matches(Regex("(?i).*[.-]$qualifier[.\\d-]*"))
28+
}
29+
}
30+
31+
tasks.withType<com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask> {
32+
resolutionStrategy {
33+
componentSelection {
34+
all {
35+
if (isNonStable(candidate.version)) {
36+
reject("Release candidate")
37+
}
38+
}
39+
}
40+
}
41+
}

canary.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ def update_sdkinfo_version(packageinfo_content):
2525

2626
for line in packageinfo_content:
2727
line = line.rstrip() # 末尾の改行のみを削除
28-
if "const val version" in line:
28+
if "const val VERSION" in line:
2929
# バージョン行のパターンマッチング
3030
version_match = re.match(
31-
r'\s*const\s+val\s+version\s*=\s*[\'"](\d+\.\d+\.\d+)(-canary\.(\d+))?[\'"]',
31+
r'\s*const\s+val\s+VERSION\s*=\s*[\'"](\d+\.\d+\.\d+)(-canary\.(\d+))?[\'"]',
3232
line,
3333
)
3434
if version_match:
@@ -43,7 +43,7 @@ def update_sdkinfo_version(packageinfo_content):
4343
new_version = f"{major_minor_patch}-canary.{canary_number + 1}"
4444

4545
# SDKInfoのバージョン行を更新
46-
updated_content.append(f' const val version = "{new_version}"')
46+
updated_content.append(f' const val VERSION = "{new_version}"')
4747
sdk_version_updated = True
4848
else:
4949
updated_content.append(line)

docs/audio_recording_pause.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# 録音一時停止/再開のロールバック設計
2+
3+
この文書では、`PeerChannelImpl` に実装されている録音一時停止/再開機構の流れと、各段階でのロールバック方法をまとめます。主な対象は `AudioDeviceModuleWrapper` とローカル音声トラック周りの防御的な処理です。
4+
5+
## 関係クラス
6+
7+
- `PeerChannelImpl`
8+
- `setAudioRecordingPaused`
9+
- `pauseAudioRecording`
10+
- `resumeAudioRecording`
11+
- `resumeWithExistingAudioTrack`
12+
- `resumeWithReinitializedAudioTrack`
13+
- `AudioDeviceModuleWrapper`
14+
- `pauseRecording`
15+
- `resumeRecording`
16+
17+
`AudioDeviceModuleWrapper``JavaAudioDeviceModule` を想定したラッパーで、専用の `HandlerThread` 上で pause/resume を実行し、最大 3,000 ミリ秒まで結果を待機します。アプリがカスタム ADM を差し込む場合はラッパーが生成されないため、録音停止/再開は利用できません。(RTCComponentFactory.kt 内の `AudioDeviceModule` セット処理参照)。
18+
また、アクセサを internal としており、外部からは直接 pause/resume を実行できないようにしています。
19+
20+
## 一時停止 (`pauseAudioRecording`)
21+
22+
1. `componentFactory.hasControllableAdm()``AudioDeviceModuleWrapper` が生成済みか確認し、未生成なら `false` を返す。
23+
2. `componentFactory.pauseControllableAdm()` を呼び出す。失敗またはタイムアウトで `false` が返った場合はロールバック不要のまま終了。
24+
3. ローカル音声トラック (`localAudioManager.track`) が存在すれば `setLocalAudioTrackEnabled(track, false)` で無効化する。
25+
- 失敗時(例外など)は ADM の `resumeRecording()` を呼び出してロールバックし、結果をログに残して `false` を返す。
26+
4. すべて成功した場合は `audioRecordingPaused = true` とし、`true` を返す。
27+
28+
### 例外安全性
29+
30+
- ADM の pause に失敗した場合は即座に処理を終了するため、後続の状態変更は発生しません。
31+
- トラックの無効化に失敗した場合のみ ADM の `resumeRecording()` を呼び出して元の状態に戻します。
32+
33+
## 再開 (`resumeAudioRecording`)
34+
35+
1. `componentFactory.hasControllableAdm()``false` の場合は録音再開を行わず `false` を返す。
36+
2. `componentFactory.resumeControllableAdm()` を呼び出す。失敗またはタイムアウト時は即終了。
37+
3. ローカル音声トラックの再開処理を `resumeWithExistingAudioTrack()` で試みる。
38+
- トラックが存在し、`setEnabled(true)``audioSender.setTrack` / `updateAudioSenderTrack` が成功すれば `SUCCESS`
39+
- 失敗した場合は `FAILURE`、トラックが存在しなければ `NEEDS_REINITIALIZATION` を返す。
40+
4. `NEEDS_REINITIALIZATION` の場合は `resumeWithReinitializedAudioTrack()` でトラックを再生成し、再度 sender へアタッチする。
41+
- ここでも失敗した場合は `FAILURE`
42+
5. 再開処理の結果が `SUCCESS` 以外だった場合は `componentFactory.pauseControllableAdm()` で ADM をロールバックし、`false` を返す。
43+
6. 成功時は `audioRecordingPaused = false` として `true` を返す。
44+
45+
### 例外安全性
46+
47+
- トラック再開処理全体を `try/catch` で囲み、例外発生時には `FAILURE` として扱います。
48+
- 任意のフェーズで失敗した場合は必ず ADM を `pauseRecording()` してロールバックするため、録音が再開しない(=マイクインジケータが消灯したまま)状況を防ぎます。
49+
50+
## ログとデバッグ
51+
52+
すべてのフェーズで `SoraLogger` による詳細なログを出しており、`[audio_recording_pause]` プレフィックスで検索するとロールバックシーケンスを追跡できます。失敗理由は `Exception` のメッセージとともに記録されるため、実機デバッグ時にどの段階で復旧が行われたかを確認できます。

0 commit comments

Comments
 (0)