Qwen3-ASR-1.7B入门指南:从零开始搭建语音识别系统

你是不是一直觉得语音识别技术很高深,离自己很远?或者想给自己的应用加个语音转文字功能,但一看到复杂的模型部署就头疼?别担心,今天咱们就来聊聊怎么用Qwen3-ASR-1.7B,从零开始搭建一个属于自己的语音识别系统。

Qwen3-ASR-1.7B是阿里开源的一个语音识别模型,别看它名字里带个“1.7B”,听起来挺大,但用起来其实挺友好的。它最大的特点就是“全能”——一个模型能识别30种语言和22种中文方言,还能处理带背景音乐的歌曲,甚至能在嘈杂环境下稳定工作。最吸引人的是,它支持流式推理,也就是说可以边录音边转文字,很适合做实时语音助手。

这篇文章就是给新手准备的,我会手把手带你走完整个流程:从环境准备、模型下载,到写第一行代码让模型跑起来,再到处理自己的音频文件。整个过程不需要你有多深的AI背景,只要会基本的Python操作就行。

1. 准备工作:搭建你的开发环境

在开始写代码之前,得先把“厨房”收拾好。这里说的厨房就是你的开发环境。别担心,步骤不多,跟着做就行。

1.1 检查你的“装备”

首先,你得有个像样的电脑。Qwen3-ASR-1.7B对硬件有些基本要求:

  • 操作系统:推荐用Linux,比如Ubuntu 20.04或更高版本。如果你用Windows,也没问题,可以用WSL2(Windows Subsystem for Linux),效果差不多。
  • Python版本:需要Python 3.8到3.11之间的版本。太老或太新的版本可能会有兼容性问题。
  • GPU:虽然不是必须的,但有GPU会快很多。模型支持CUDA,所以如果你有NVIDIA显卡(显存最好8GB以上),体验会好很多。没有GPU也能用CPU跑,就是慢点。
  • 内存:建议16GB以上,因为模型本身和推理过程都需要不少内存。

怎么检查自己电脑合不合格呢?打开终端(Linux/macOS)或命令提示符(Windows),输入:

python --version

看看是不是3.8到3.11之间的版本。如果有GPU,可以再装个PyTorch测试一下:

import torch
print(torch.cuda.is_available())  # 如果是True,说明GPU可用

1.2 创建独立的Python环境

这是个好习惯,就像做饭前先洗手一样。创建一个独立的环境可以避免各种包版本冲突。我推荐用conda或者venv,这里用venv举例,因为它简单:

# 创建一个叫qwen-asr的环境
python -m venv qwen-asr-env

# 激活环境
# Linux/macOS:
source qwen-asr-env/bin/activate
# Windows:
qwen-asr-env\Scripts\activate

激活后,你的命令行前面应该会出现(qwen-asr-env)的提示,说明你现在在这个环境里了。

1.3 安装必要的软件包

现在可以安装我们需要的包了。核心是qwen-asr这个包,它包含了模型和推理工具。另外还需要一些辅助包:

# 升级pip,确保是最新版本
pip install --upgrade pip

# 安装qwen-asr,如果要用GPU推理,记得带上[vllm]
pip install qwen-asr[vllm]

# 安装一些常用的辅助包
pip install torch torchaudio
pip install soundfile  # 用于读取音频文件
pip install requests   # 如果需要通过HTTP调用

这里有个小细节:qwen-asr[vllm]里的vllm是专门为GPU优化推理速度的。如果你只用CPU,或者显存很小(比如小于4GB),可以只装pip install qwen-asr,但速度会慢不少。

安装过程可能会花几分钟,取决于你的网速。如果遇到网络问题,可以考虑换个pip源,比如用清华的镜像:

pip install qwen-asr[vllm] -i https://pypi.tuna.tsinghua.edu.cn/simple

2. 下载模型:把“大脑”请回家

环境准备好了,现在需要把模型本身下载下来。Qwen3-ASR-1.7B模型文件大概7GB左右,所以需要点时间和空间。

2.1 设置缓存路径(可选但推荐)

模型文件不小,你肯定不想让它随便下载到系统盘占空间。可以设置一个专门的目录来存放:

# Linux/macOS
export MODELSCOPE_CACHE=/path/to/your/cache
# Windows
set MODELSCOPE_CACHE=D:\AI\Models

如果你想让这个设置永久生效,可以把上面的命令加到shell配置文件里(比如.bashrc.zshrc)。

2.2 实际下载模型

下载模型很简单,一行命令就行:

from modelscope import snapshot_download

# 下载Qwen3-ASR-1.7B模型
model_dir = snapshot_download('Qwen/Qwen3-ASR-1.7B')
print(f"模型下载到了: {model_dir}")

或者直接用命令行:

python -c "from modelscope import snapshot_download; snapshot_download('Qwen/Qwen3-ASR-1.7B')"

第一次运行会下载模型文件,时间取决于你的网速。我这边大概花了20分钟。下载完成后,你会看到类似这样的路径:~/.cache/modelscope/hub/Qwen/Qwen3-ASR-1.7B

如果下载过程中断了,别担心,重新运行命令会继续下载,不会从头开始。

2.3 验证下载是否成功

下载完可以简单检查一下:

import os

model_path = os.path.join(os.environ.get("MODELSCOPE_CACHE", ""), 
                         "hub", "Qwen", "Qwen3-ASR-1.7B")
if os.path.exists(model_path):
    print("✓ 模型下载成功!")
    # 看看里面有什么文件
    files = os.listdir(model_path)
    print(f"找到 {len(files)} 个文件,包括:")
    for f in files[:5]:  # 只显示前5个
        print(f"  - {f}")
else:
    print("✗ 模型路径不存在,可能需要重新下载")

正常情况下,你应该能看到config.jsonmodel.safetensors等文件。

3. 第一个语音识别程序:让模型开口说话

好了,最激动人心的部分来了——写代码让模型跑起来!我们从最简单的开始:识别一段网络上的音频。

3.1 基础版:识别在线音频

先来个最简单的例子,识别模型作者提供的一个示例音频:

import torch
from qwen_asr import Qwen3ASRModel

# 加载模型
model = Qwen3ASRModel.from_pretrained(
    "Qwen/Qwen3-ASR-1.7B",  # 模型名称,会自动从缓存加载
    torch_dtype=torch.bfloat16,  # 使用bfloat16精度,节省显存
    device_map="cuda:0",  # 使用GPU,如果是CPU就改成"cpu"
)

# 识别一段在线音频
results = model.transcribe(
    audio="https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen3-ASR-Repo/asr_en.wav",
    language=None,  # 设为None让模型自动检测语言
)

# 打印结果
print(f"检测到的语言: {results[0].language}")
print(f"识别出的文本: {results[0].text}")

运行这段代码,你应该能看到类似这样的输出:

检测到的语言: English
识别出的文本: This is a sample audio for testing the Qwen3 ASR model.

是不是很简单?不到10行代码就完成了一次语音识别。让我解释一下关键点:

  • torch_dtype=torch.bfloat16:这个设置很重要。bfloat16是一种浮点数格式,比标准的float32占用一半显存,但精度损失很小,非常适合大模型推理。
  • device_map="cuda:0":指定用哪个GPU。如果你有多块显卡,可以改成"cuda:1"等。
  • language=None:让模型自动检测语言。如果你知道音频是什么语言,可以指定,比如language="Chinese",这样识别准确率会更高。

3.2 处理本地音频文件

实际应用中,我们更多是处理本地的音频文件。来试试看:

from qwen_asr import Qwen3ASRModel
import torch

# 加载模型(和之前一样)
model = Qwen3ASRModel.from_pretrained(
    "Qwen/Qwen3-ASR-1.7B",
    torch_dtype=torch.bfloat16,
    device_map="cuda:0",
)

# 识别本地音频文件
results = model.transcribe(
    audio="/path/to/your/audio.wav",  # 改成你的音频文件路径
    language="Chinese",  # 假设是中文音频
)

print(f"识别结果: {results[0].text}")

这里有几个实用的小技巧:

  1. 音频格式:模型支持WAV、MP3、FLAC等常见格式。如果是MP3,系统会自动转换。
  2. 文件路径:可以用绝对路径,也可以用相对路径。如果文件在当前目录下,直接写文件名就行。
  3. 长音频处理:模型能一次性处理最长20分钟的音频。如果超过20分钟,需要自己先切分成小段。

3.3 批量处理多个文件

如果你有一堆音频文件要处理,可以这样:

import os
from qwen_asr import Qwen3ASRModel
import torch

model = Qwen3ASRModel.from_pretrained(
    "Qwen/Qwen3-ASR-1.7B",
    torch_dtype=torch.bfloat16,
    device_map="cuda:0",
)

# 假设你的音频文件都在audio_folder目录下
audio_folder = "./audio_files"
output_file = "./transcriptions.txt"

with open(output_file, "w", encoding="utf-8") as f:
    for filename in os.listdir(audio_folder):
        if filename.endswith((".wav", ".mp3", ".flac")):
            filepath = os.path.join(audio_folder, filename)
            print(f"正在处理: {filename}")
            
            try:
                results = model.transcribe(audio=filepath, language=None)
                transcription = results[0].text
                f.write(f"{filename}: {transcription}\n")
                print(f"  完成: {transcription[:50]}...")  # 只显示前50个字
            except Exception as e:
                print(f"  处理失败: {e}")
                f.write(f"{filename}: [ERROR] {e}\n")

print(f"所有文件处理完成,结果保存在: {output_file}")

这个脚本会遍历指定文件夹下的所有音频文件,把识别结果保存到一个文本文件里。即使某个文件处理失败,也会继续处理下一个。

4. 进阶功能:探索模型的更多能力

基础的识别会了,现在来看看Qwen3-ASR-1.7B还有什么厉害的功能。

4.1 流式识别:边听边转写

这是Qwen3-ASR的一个亮点功能,特别适合做实时语音助手。想象一下,用户一边说话,屏幕上就一边出文字,就像字幕一样。

import numpy as np
import soundfile as sf
from qwen_asr import Qwen3ASRModel

# 注意:流式识别需要用特殊的加载方式
asr = Qwen3ASRModel.LLM(
    model="Qwen/Qwen3-ASR-1.7B",
    gpu_memory_utilization=0.8,  # GPU内存使用率,0.8表示80%
    max_new_tokens=32,  # 每次生成的最大token数,流式识别可以设小点
)

# 先加载一个音频文件
audio_path = "test.wav"
wav, sample_rate = sf.read(audio_path, dtype="float32")

# 确保是16kHz采样率(模型要求)
if sample_rate != 16000:
    # 简单的重采样(实际应用可以用librosa等库)
    duration = len(wav) / sample_rate
    new_length = int(duration * 16000)
    wav_16k = np.interp(
        np.linspace(0, len(wav)-1, new_length),
        np.arange(len(wav)),
        wav
    )
else:
    wav_16k = wav

# 初始化流式状态
state = asr.init_streaming_state(
    unfixed_chunk_num=2,    # 不确定的块数
    unfixed_token_num=5,    # 不确定的token数
    chunk_size_sec=2.0,     # 每块2秒
)

# 模拟流式输入:每次处理500ms的音频
chunk_ms = 500
chunk_samples = int(chunk_ms / 1000.0 * 16000)

pos = 0
chunk_id = 0
while pos < len(wav_16k):
    # 取一段音频
    chunk = wav_16k[pos:pos + chunk_samples]
    pos += len(chunk)
    chunk_id += 1
    
    # 流式识别
    asr.streaming_transcribe(chunk, state)
    
    # 打印中间结果
    print(f"[块 {chunk_id:03d}] 语言: {state.language} | 文本: {state.text}")

# 结束流式识别
asr.finish_streaming_transcribe(state)
print(f"[最终结果] 语言: {state.language} | 文本: {state.text}")

运行这个脚本,你会看到文字随着音频播放逐步出现。这种流式识别有几个好处:

  • 低延迟:不用等整段话说完,边说边出结果
  • 内存友好:不用一次性加载整个长音频
  • 实时反馈:适合对话场景

4.2 多语言和方言识别

Qwen3-ASR-1.7B支持30种语言和22种中文方言,这个能力很实用。比如你有一段粤语音频:

from qwen_asr import Qwen3ASRModel
import torch

model = Qwen3ASRModel.from_pretrained(
    "Qwen/Qwen3-ASR-1.7B",
    torch_dtype=torch.bfloat16,
    device_map="cuda:0",
)

# 粤语识别
results = model.transcribe(
    audio="cantonese_audio.wav",
    language=None,  # 让模型自动检测
)

print(f"检测语言: {results[0].language}")
print(f"识别文本: {results[0].text}")

# 你也可以强制指定语言
results_forced = model.transcribe(
    audio="cantonese_audio.wav",
    language="Cantonese",  # 强制指定为粤语
)
print(f"强制粤语识别: {results_forced[0].text}")

模型能自动检测是普通话、粤语还是其他方言,准确率还挺高的。我试过一段带点口音的“广普”(广东口音的普通话),它也能正确识别。

4.3 处理特殊场景:歌声、嘈杂环境

Qwen3-ASR在复杂场景下表现不错,比如带背景音乐的歌曲:

# 识别带背景音乐的歌曲
song_results = model.transcribe(
    audio="song_with_music.mp3",
    language="Chinese",  # 如果是中文歌
)

print(f"歌曲识别: {song_results[0].text}")

或者在嘈杂环境下:

# 嘈杂环境下的语音
noisy_results = model.transcribe(
    audio="noisy_meeting.wav",
    language="English",
    # 模型内部有降噪处理,不需要额外参数
)

print(f"嘈杂环境识别: {noisy_results[0].text}")

根据官方测试,即使在信噪比很低(很吵)的环境下,模型的错误率仍然很低。这对于会议录音、户外采访等场景很有用。

5. 常见问题与解决方案

新手在使用过程中可能会遇到一些问题,这里我整理了几个常见的:

5.1 显存不够怎么办?

Qwen3-ASR-1.7B需要不少显存。如果你看到类似CUDA out of memory的错误,可以试试这些方法:

# 方法1:使用更低的精度
model = Qwen3ASRModel.from_pretrained(
    "Qwen/Qwen3-ASR-1.7B",
    torch_dtype=torch.float16,  # 用float16代替bfloat16(如果支持)
    device_map="cuda:0",
)

# 方法2:使用CPU(慢,但能跑)
model = Qwen3ASRModel.from_pretrained(
    "Qwen/Qwen3-ASR-1.7B",
    torch_dtype=torch.float32,
    device_map="cpu",  # 强制用CPU
)

# 方法3:使用0.6B的小模型(功能差不多,精度稍低)
model = Qwen3ASRModel.from_pretrained(
    "Qwen/Qwen3-ASR-0.6B",  # 改用0.6B版本
    torch_dtype=torch.bfloat16,
    device_map="cuda:0",
)

0.6B版本只有1.7B版本三分之一的大小,但识别能力下降不多,是个不错的折中选择。

5.2 音频太长怎么办?

模型最多处理20分钟音频。如果超过这个长度,需要自己切分:

import librosa
from qwen_asr import Qwen3ASRModel

def transcribe_long_audio(audio_path, chunk_minutes=15):
    """处理长音频,自动切分成块"""
    model = Qwen3ASRModel.from_pretrained(
        "Qwen/Qwen3-ASR-1.7B",
        torch_dtype=torch.bfloat16,
        device_map="cuda:0",
    )
    
    # 加载音频
    y, sr = librosa.load(audio_path, sr=16000)  # 统一重采样到16kHz
    chunk_samples = chunk_minutes * 60 * sr
    
    results = []
    for i in range(0, len(y), chunk_samples):
        chunk = y[i:i + chunk_samples]
        
        # 保存临时文件
        temp_path = f"temp_chunk_{i//chunk_samples}.wav"
        sf.write(temp_path, chunk, sr)
        
        # 识别这一块
        chunk_result = model.transcribe(audio=temp_path, language=None)
        results.append(chunk_result[0].text)
        
        # 清理临时文件
        os.remove(temp_path)
        
        print(f"完成第 {i//chunk_samples + 1} 块")
    
    # 合并结果
    full_text = " ".join(results)
    return full_text

5.3 识别结果有数字、符号格式问题

有时候模型会把“123”识别成“一百二十三”,或者日期格式不统一。可以在后处理阶段修复:

import re

def post_process_text(text):
    """后处理识别文本"""
    # 修复常见的数字格式问题
    text = re.sub(r'(\d+)\s*点\s*(\d+)', r'\1.\2', text)  # "3 点 14" -> "3.14"
    text = re.sub(r'(\d+)\s*分之\s*(\d+)', r'\1/\2', text)  # "3 分之 4" -> "3/4"
    
    # 修复英文大小写(句首大写)
    sentences = text.split('. ')
    sentences = [s.capitalize() for s in sentences]
    text = '. '.join(sentences)
    
    return text

# 使用示例
raw_result = "今天下午3 点 30分开会"
processed = post_process_text(raw_result)
print(processed)  # "今天下午3.30分开会"

5.4 如何提高识别准确率?

如果你发现某些场景下识别不准,可以试试这些方法:

  1. 指定语言:如果你知道音频的语言,一定要指定language参数。
  2. 音频质量:确保音频清晰,采样率合适(16kHz最佳)。
  3. 分段处理:特别长的音频可以切成10-15分钟一段。
  4. 多次尝试:有时候同样的音频,两次识别结果可能略有不同,可以取最好的那个。

6. 实际应用:搭建一个简单的语音转文字服务

学了这么多,我们来做个实际有用的东西:一个简单的Web服务,可以上传音频文件,返回文字结果。

6.1 用Flask搭建后端

# app.py
from flask import Flask, request, jsonify
import os
import tempfile
from qwen_asr import Qwen3ASRModel
import torch

app = Flask(__name__)

# 全局加载模型(启动时加载一次)
model = None

def load_model():
    global model
    if model is None:
        print("正在加载模型...")
        model = Qwen3ASRModel.from_pretrained(
            "Qwen/Qwen3-ASR-1.7B",
            torch_dtype=torch.bfloat16,
            device_map="cuda:0",
        )
        print("模型加载完成")

@app.route('/transcribe', methods=['POST'])
def transcribe_audio():
    """接收音频文件,返回识别结果"""
    load_model()
    
    if 'audio' not in request.files:
        return jsonify({'error': '没有上传音频文件'}), 400
    
    audio_file = request.files['audio']
    language = request.form.get('language', None)
    
    # 保存临时文件
    with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as tmp:
        audio_file.save(tmp.name)
        temp_path = tmp.name
    
    try:
        # 识别
        results = model.transcribe(
            audio=temp_path,
            language=language,
        )
        
        response = {
            'success': True,
            'language': results[0].language,
            'text': results[0].text,
            'confidence': results[0].confidence if hasattr(results[0], 'confidence') else None,
        }
        
    except Exception as e:
        response = {
            'success': False,
            'error': str(e),
        }
    finally:
        # 清理临时文件
        os.unlink(temp_path)
    
    return jsonify(response)

if __name__ == '__main__':
    # 先加载模型
    load_model()
    # 启动服务
    app.run(host='0.0.0.0', port=5000, debug=True)

6.2 简单的HTML前端

<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>语音识别服务</title>
</head>
<body>
    <h1>上传音频文件进行识别</h1>
    
    <form id="uploadForm">
        <div>
            <label for="audioFile">选择音频文件:</label>
            <input type="file" id="audioFile" accept=".wav,.mp3,.flac" required>
        </div>
        
        <div>
            <label for="language">语言(可选):</label>
            <select id="language">
                <option value="">自动检测</option>
                <option value="Chinese">中文</option>
                <option value="English">英文</option>
                <option value="Cantonese">粤语</option>
                <option value="Japanese">日语</option>
            </select>
        </div>
        
        <button type="submit">开始识别</button>
    </form>
    
    <div id="result" style="margin-top: 20px; padding: 10px; border: 1px solid #ccc; display: none;">
        <h3>识别结果:</h3>
        <p><strong>语言:</strong> <span id="resultLanguage"></span></p>
        <p><strong>文本:</strong> <span id="resultText"></span></p>
    </div>
    
    <script>
        document.getElementById('uploadForm').addEventListener('submit', async (e) => {
            e.preventDefault();
            
            const fileInput = document.getElementById('audioFile');
            const languageSelect = document.getElementById('language');
            const formData = new FormData();
            
            formData.append('audio', fileInput.files[0]);
            formData.append('language', languageSelect.value);
            
            try {
                const response = await fetch('http://localhost:5000/transcribe', {
                    method: 'POST',
                    body: formData,
                });
                
                const result = await response.json();
                
                if (result.success) {
                    document.getElementById('resultLanguage').textContent = result.language;
                    document.getElementById('resultText').textContent = result.text;
                    document.getElementById('result').style.display = 'block';
                } else {
                    alert('识别失败: ' + result.error);
                }
            } catch (error) {
                alert('请求失败: ' + error.message);
            }
        });
    </script>
</body>
</html>

6.3 运行服务

  1. 启动后端:
python app.py
  1. 用浏览器打开index.html,选择音频文件上传。

  2. 稍等片刻(取决于音频长度),就能看到识别结果。

这个简单的服务可以扩展成很多有用的应用,比如:

  • 会议录音自动整理
  • 播客内容转文字
  • 视频字幕生成
  • 语音笔记应用

7. 总结与下一步建议

走完这一趟,你应该已经掌握了Qwen3-ASR-1.7B的基本用法。从环境搭建到模型下载,从基础识别到流式处理,再到搭建一个完整的服务,我们一步步都走过了。

实际用下来,我感觉Qwen3-ASR-1.7B确实是个不错的语音识别工具。它的多语言支持很实用,流式识别功能做实时应用很方便,而且在嘈杂环境下的表现比我想象的要好。对于刚接触语音识别的新手来说,它提供的API足够简单,文档也还算清晰,上手难度不大。

不过也有些地方需要注意。模型文件比较大,下载需要时间和空间。推理对硬件有一定要求,特别是如果想用流式识别,GPU显存不能太小。另外,虽然官方说支持30种语言,但有些小语种的识别效果可能不如中英文那么稳定。

如果你打算深入使用,我有几个建议。首先,从简单的场景开始,比如清晰的单人语音,熟悉了再尝试复杂场景。其次,关注一下0.6B版本,它在速度和资源消耗上更有优势,适合部署在资源有限的环境。最后,记得处理长音频时要自己切分,模型一次只能处理20分钟。

语音识别技术现在越来越成熟,像Qwen3-ASR这样的开源模型让普通开发者也能用上以前只有大公司才有的能力。无论是做个人项目,还是为企业开发应用,这都是个不错的起点。希望这篇指南能帮你迈出第一步,后面就靠你自己探索更多可能性了。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐