[Python] DTLS handshake fails with "no SRTP profile negotiated" when streaming from ffmpeg...

Discussão em 'Python' iniciado por Stack, Novembro 25, 2025.

  1. Stack

    Stack Membro Participativo

    I'm trying to test low-latency video streaming using ffmpeg's WHIP protocol to stream to an aiortc-based Python server. The ICE connection completes successfully, but the DTLS handshake fails with "no SRTP profile negotiated".

    My ffmpeg build (nightly 20251120) is compiled with --enable-schannel instead of --enable-openssl, I don't know if this is the source of the failed handshake.

    Server code:

    from aiohttp import web
    from aiortc import RTCPeerConnection, RTCSessionDescription, RTCConfiguration, RTCIceServer
    import logging

    logging.basicConfig(level=logging.DEBUG)
    logger = logging.getLogger(__name__)

    whip_sessions = {}

    async def whip_endpoint(request):
    global whip_sessions
    sdp = await request.text()
    config = RTCConfiguration(
    iceServers=[RTCIceServer(urls=["stun:stun.l.google.com:19302"])]
    )
    pc = RTCPeerConnection(configuration=config)

    session_id = id(pc)
    whip_sessions[session_id] = {
    'pc': pc,
    'video_track': None
    }

    @pc.on('track')
    async def on_track(track):
    global whip_sessions
    if track.kind == 'video':
    whip_sessions[session_id]['video_track'] = track
    logger.info('subscribed to video stream')

    await pc.setRemoteDescription(
    RTCSessionDescription(sdp=sdp, type='offer')
    )
    answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)

    return web.Response(
    content_type='application/sdp',
    text=pc.localDescription.sdp,
    status=201,
    headers={
    'Location': f'/whip/{session_id}'
    }
    )

    async def whip_delete(request):
    global whip_sessions
    session_id = int(request.match_info['id'])
    session = whip_sessions.get(session_id)
    if session:
    await session['pc'].close()
    whip_sessions.pop(session_id, None)
    logger.info(f"Session {session_id} terminated")
    return web.Response(status=200)
    else:
    logger.warning(f"Session {session_id} not found")
    return web.Response(status=404, text='Session not found')


    if __name__ == '__main__':
    app = web.Application()
    app.router.add_post('/whip', whip_endpoint)
    app.router.add_delete('/whip/{id}', whip_delete)
    web.run_app(app, host='127.0.0.1', port=8080)


    ffmpeg command:

    ffmpeg -re -f lavfi -i testsrc=size=640x360:rate=30 -f lavfi -i sine=frequency=440:sample_rate=48000 \
    -c:v libx264 -preset ultrafast -tune zerolatency -b:v 500k -g 30 -pix_fmt yuv420p \
    -c:a libopus -b:a 128k -ac 2 \
    -f whip http://localhost:8080/whip


    debug output:

    INFO:aioice.ice:Connection(0) ICE completed
    DEBUG:aiortc.rtcicetransport:RTCIceTransport(controlled) - checking -> completed
    DEBUG:aiortc.rtcpeerconnection:RTCPeerConnection() iceConnectionState checking -> completed DEBUG:aiortc.rtcdtlstransport:RTCDtlsTransport(client) - State.NEW -> State.CONNECTING
    DEBUG:aiortc.rtcdtlstransport:RTCDtlsTransport(client) x DTLS handling timeout
    DEBUG:aiortc.rtcdtlstransport:RTCDtlsTransport(client) x DTLS handshake failed (no SRTP profile negotiated) DEBUG:aiortc.rtcdtlstransport:RTCDtlsTransport(client) - State.CONNECTING -> State.FAILED
    DEBUG:aiortc.rtcpeerconnection:RTCPeerConnection() connectionState connecting -> failed


    Has anyone successfully streamed from ffmpeg to aiortc using WHIP?

    Continue reading...

Compartilhe esta Página