Flutter音频处理插件vad的使用

发布于 1周前 作者 zlyuanteng 来自 Flutter

Flutter音频处理插件vad的使用

示例代码

// main.dart
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:vad/vad.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'VAD Example',
      theme: ThemeData.dark().copyWith(
        primaryColor: Colors.blue,
        scaffoldBackgroundColor: const Color(0xFF121212),
        cardColor: const Color(0xFF1E1E1E),
        sliderTheme: SliderThemeData(
          activeTrackColor: Colors.blue[400],
          inactiveTrackColor: Colors.grey[800],
          thumbColor: Colors.blue[300],
          overlayColor: Colors.blue.withAlpha(32),
        ),
        elevatedButtonTheme: ElevatedButtonThemeData(
          style: ElevatedButton.styleFrom(
            backgroundColor: Colors.blue[700],
            foregroundColor: Colors.white,
          ),
        ),
        textButtonTheme: TextButtonThemeData(
          style: TextButton.styleFrom(
            foregroundColor: Colors.blue[300],
          ),
        ),
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final _vadHandler = VadHandler.create(isDebug: true);
  bool isListening = false;
  int frameSamples = 1536; // 1帧 = 1536样本 = 96ms
  int minSpeechFrames = 3;

  @override
  void initState() {
    super.initState();
    _setupVadHandler();
  }

  void _setupVadHandler() {
    _vadHandler.onSpeechStart.listen((_) {
      debugPrint('Speech detected.');
    });

    _vadHandler.onSpeechEnd.listen((List<double> samples) {
      setState(() {
        print('Speech ended, first 10 samples: ${samples.take(10).toList()}');
      });
    });

    _vadHandler.onError.listen((String message) {
      debugPrint('Error: $message');
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("VAD Example"),
        backgroundColor: Colors.black,
        elevation: 0,
      ),
      body: Column(
        children: [
          Expanded(
            child: ListView.builder(
              padding: const EdgeInsets.symmetric(vertical: 8.0),
              itemCount: 10,
              itemBuilder: (context, index) {
                return ListTile(
                  title: Text('Recording ${index + 1}'),
                  subtitle: Text('Speech start'),
                  onTap: () {
                    if (_vadHandler.isListening) {
                      _vadHandler.stopListening();
                    } else {
                      _vadHandler.startListening();
                    }
                    setState(() {
                      isListening = !isListening;
                    });
                  },
                );
              },
            ),
          ),
          Container(
            padding: const EdgeInsets.all(16.0),
            decoration: BoxDecoration(
              color: Colors.black,
              boxShadow: [
                BoxShadow(
                  color: Colors.black.withOpacity(0.3),
                  spreadRadius: 1,
                  blurRadius: 10,
                  offset: const Offset(0, -1),
                ),
              ],
            ),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                ElevatedButton.icon(
                  onPressed: () async {
                    final status = await Permission.microphone.request();
                    debugPrint("Microphone permission status: $status");
                  },
                  icon: Icon(isListening ? Icons.stop : Icons.mic),
                  label:
                      Text(isListening ? "Stop Listening" : "Start Listening"),
                  style: ElevatedButton.styleFrom(
                    minimumSize: const Size(double.infinity, 48),
                  ),
                ),
                const SizedBox(height: 8),
                TextButton.icon(
                  onPressed: () async {
                    final status = await Permission.microphone.request();
                    debugPrint("Microphone permission status: $status");
                  },
                  icon: const Icon(Icons.settings_voice),
                  label: const Text("Request Microphone Permission"),
                  style: TextButton.styleFrom(
                    minimumSize: const Size(double.infinity, 48),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

示例代码解释

  1. 初始化VAD Handler

    final _vadHandler = VadHandler.create(isDebug: true);
    

    创建一个VAD处理器实例,并启用调试模式。

  2. 监听事件

    _vadHandler.onSpeechStart.listen((_) {
      debugPrint('Speech detected.');
    });
    
    _vadHandler.onSpeechEnd.listen((List<double> samples) {
      setState(() {
        print('Speech ended, first 10 samples: ${samples.take(10).toList()}');
      });
    });
    
    _vadHandler.onError.listen((String message) {
      debugPrint('Error: $message');
    });
    

    监听语音开始、结束和错误事件。

  3. 控制监听状态

    if (_vadHandler.isListening) {
      _vadHandler.stopListening();
    } else {
      _vadHandler.startListening();
    }
    

    根据当前是否在监听,启动或停止监听。

  4. 请求麦克风权限

    final status = await Permission.microphone.request();
    

    请求麦克风权限。

  5. UI布局

    Expanded(child: ListView.builder(...))
    

更多关于Flutter音频处理插件vad的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter音频处理插件vad的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用Voice Activity Detection (VAD) 音频处理插件的示例代码。这个示例假设你已经有一个Flutter项目,并且已经添加了相关的VAD插件(假设插件名为flutter_vad,实际使用时请根据具体插件的文档和名称进行调整)。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加VAD插件的依赖。注意,这里假设插件名为flutter_vad,你需要根据实际情况替换为正确的插件名称。

dependencies:
  flutter:
    sdk: flutter
  flutter_vad: ^x.y.z  # 替换为实际的版本号

2. 导入插件并初始化

在你的Dart文件中(例如main.dart),导入插件并进行初始化。

import 'package:flutter/material.dart';
import 'package:flutter_vad/flutter_vad.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter VAD Example'),
        ),
        body: VADPage(),
      ),
    );
  }
}

class VADPage extends StatefulWidget {
  @override
  _VADPageState createState() => _VADPageState();
}

class _VADPageState extends State<VADPage> {
  late FlutterVad flutterVad;
  bool isRecording = false;

  @override
  void initState() {
    super.initState();
    flutterVad = FlutterVad();
    flutterVad.init().then((_) {
      print("VAD initialized");
    }).catchError((e) {
      print("Failed to initialize VAD: $e");
    });
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        children: [
          Text("Voice Activity Detection Example"),
          SizedBox(height: 20),
          ElevatedButton(
            onPressed: () {
              setState(() {
                isRecording = !isRecording;
              });
              if (isRecording) {
                startRecording();
              } else {
                stopRecording();
              }
            },
            child: Text(isRecording ? "Stop Recording" : "Start Recording"),
          ),
        ],
      ),
    );
  }

  void startRecording() {
    // 这里你需要实现音频录制逻辑,并将音频数据传递给VAD进行处理
    // 假设你有一个音频录制方法`recordAudio`,它返回一个音频数据流
    recordAudio().listen((audioData) {
      flutterVad.detectActivity(audioData).then((result) {
        print("VAD Result: ${result ? "Voice Detected" : "No Voice"}");
      }).catchError((e) {
        print("VAD Error: $e");
      });
    });
  }

  void stopRecording() {
    // 停止音频录制并清理资源
    // 这里你需要实现停止录制的逻辑
  }

  // 这是一个示例的音频录制方法,你需要根据你的需求来实现
  Stream<Uint8List> recordAudio() {
    // 返回一个模拟的音频数据流
    return Stream.fromIterable([Uint8List.fromList([/* 模拟音频数据 */])]);
  }
}

3. 实现音频录制

上面的代码示例中,recordAudio方法是一个占位符,你需要根据你的项目需求来实现音频录制功能。通常,这涉及到使用Flutter的音频录制插件(如audioplayersflutter_sound)来捕获音频数据,并将这些数据传递给VAD插件进行处理。

注意事项

  1. 插件兼容性:确保你使用的VAD插件与你的Flutter版本兼容。
  2. 音频格式:确保传递给VAD插件的音频数据格式符合插件的要求(例如采样率、位深度等)。
  3. 错误处理:在实际应用中,添加更多的错误处理和日志记录,以便于调试和维护。
  4. 权限:在Android和iOS上,确保你已经请求并获得了音频录制的权限。

由于具体的VAD插件可能会有不同的API和用法,因此建议查阅相关插件的官方文档以获取更详细的信息和示例代码。

回到顶部