【WebRTC】SDP の m-line 順序エラーとその解決方法

今回は、こちらの記事で構築したSFUを使って何度か通話を行った際、エラーが発生することがあったので、その内容を記事にしてみました。

発生したエラー

通話を何度か繰り返した際、以下のようなエラーが出て通話に失敗することがありました。

Failed to set local offer sdp: The order of m-lines in subsequent offer doesn't match order from previous offer/answer.

このエラーは、SDP(Session Description Protocol)で定義されるメディア情報の順番が、最初の Offer/Answer 以降で一致しなかった場合に発生します。

SDP における「m-line」とは?

SDP の中では、通信するメディア情報(音声・映像・データなど)を m-line(media line)として記述します。
たとえば、以下のような SDP の場合は、audiovideo の順で定義されています。

m=audio 9 UDP/TLS/RTP/SAVPF 111 103
m=video 9 UDP/TLS/RTP/SAVPF 96 97

この順番はセッション中に厳密に保持されるべきであり、異なる順序での offer/answer を行うと、WebRTC がエラーを返してきます

解決方法

解決方法はシンプルで、Track(Producer)の追加順を毎回固定することです。

具体的には以下のような感じです。

// 明示的に audio → video の順で producer を追加する
produceMutex.withLock {
    try {
        // 音声から必ず先に produce
        audioProducer = sendTransport?.produce(listener, audioTrack, null, null, null)
        delay(500) // 順序安定のために少し待つ
        videoProducer = sendTransport?.produce(listener, videoTrack, null, null, null)
    } catch (e: Throwable) {
        Logger.e(TAG, "produceAudioAndVideo failed", e)
    }
}

このエラーは、「SDP の順序なんて意識してないよ」という方にはなかなか気づきづらい落とし穴です。

WebRTC セッションを安定させるには、Track(Producer)の追加順を固定するというルールを守ることが重要なようです。