Migrating from Deepgram / AssemblyAI to Self-Hosted FunASR: Integration and Acceptance

A self-hosted transcription migration is an application-contract change: upload protocols, model selection, authentication, result structures and operational ownership all matter. This guide covers file transcription with the packaged funasr-server in FunASR 1.4.15. It is not a direct replacement for proprietary Deepgram / AssemblyAI APIs or SDKs, nor a promise of complete cloud-service feature parity.

List migration requirements before choosing a model

Application layerWhat to verify
Request protocolMap the existing SDK or HTTP call to the target route, multipart file upload and declared fields. Check addresses, headers and parameters.
Task lifecycleThe local example is a single file-upload transcription, not a streaming session, asynchronous job queue or webhook service. Applications depending on those workflows need separate implementation or an appropriate deployment service.
Result structureMap text, time units, segments, speaker labels and empty results explicitly. Diarization labels are not verified real-world speaker identities; available information differs by model.
Failure handlingCheck authentication failures, invalid files, timeouts, retries and overload behavior. A client timeout does not prove that background inference has been cancelled.
Operational ownershipPlan capacity, monitoring, upgrades, retention and recovery. Evaluate your own recordings instead of choosing from unverified language or price rankings.

Start with model selection and the deployment matrix. For transcription plus speaker diarization, evaluate the integration path for the third-party MOSS-Transcribe-Diarize model. Do not project one backend's capabilities onto every FunASR service.

Minimal local integration: verify JSON text first

Prerequisite: a separate, already prepared and verified FunASR 1.4.15 environment. This is not a from-scratch installation tutorial. The Python and funasr-server commands must use the same activated environment, with funasr==1.4.15, PyTorch, audio dependencies, FastAPI, Uvicorn, python-multipart, model-weight access and an audio file ready. Use the installation guide for platform dependencies; other versions require a fresh behavior check.

python -c 'from importlib.metadata import version; assert version("funasr") == "1.4.15", version("funasr")'
python -m pip check

The version assertion and pip check inspect package metadata; they do not prove working CUDA, audio decoding or acoustic inference. The command below explicitly selects SenseVoice CPU for an integration check, not a performance recommendation. Do not start two servers on the same port. The separate repository example HTTP service guide is an implementation comparison: it prepares and starts the example server, not the packaged 1.4.15 environment required here.

funasr-server --host 127.0.0.1 --port 8000 --model sensevoice --device cpu

From another terminal on the same host, submit an audio.wav file you are authorized to process. Transcript text is printed to the terminal; keep private results out of public logs.

curl --fail --show-error --silent --max-time 120 \
  http://127.0.0.1:8000/v1/audio/transcriptions \
  -F "file=@audio.wav" \
  -F "model=sensevoice" \
  -F "response_format=json"

The expected structure is a JSON object containing text; its content depends on the audio and model. The 120-second client timeout is an example, not an audio-duration or throughput guarantee. For a basic OpenAI Python SDK call, see the local transcription integration guide. This does not make the original vendor SDK reusable unchanged.

Make response-format limits explicit

response_formatPackaged handler behavior
jsonReturns a JSON object containing text.
verbose_jsonReturns structured JSON with fields including segments and duration. Actual timing and speaker information depend on the model and result.
textReturns a JSON string, not a plain-text response.
srtDoes not produce SRT subtitles; this value reaches the JSON text-object branch. HTTP 200 does not prove that a subtitle file was returned.
vttDoes not produce VTT subtitles; this value also reaches the JSON text-object branch.

The route declares file, model, language, response_format and the extension spk. An extra field being accepted does not prove it was applied.

For the packaged service, verify fields against its running /openapi.json over a private or restricted operational path and the pinned packaged handler source. The example-service API schema documents a different implementation, not this packaged handler. Packaged, repository example, vLLM and llama.cpp servers do not share every default, field or response shape.

Three acceptance gates before rollout

  1. Contract: run representative controlled requests against old and new implementations. Check fields, text parsing, time units, failures and timeouts; one HTTP 200 is not complete compatibility evidence.
  2. Quality: use business recordings to check key entities, overlapping speakers, segmentation and difficult audio. Follow the meeting-transcript acceptance checklist and record model, hardware and version.
  3. Security and operations: test gateway authentication and prevention of backend bypass. A container's 127.0.0.1 is the container itself; design a restricted network for cross-container access. Assess compute, storage, bandwidth, monitoring and maintenance costs, and review the selected model-weight license separately.

Self-hosting provides control over data processing, not an automatic guarantee of no-disk audio handling, transcript-free logs or zero cost. Include temporary files, proxies, clients and retention policies in the review. This article does not compare current vendor prices or claim new accuracy or performance results.

Related posts