Flutter音频编码插件flutter_lame的使用

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

Flutter音频编码插件flutter_lame的使用

flutter_lame 是一个用于将音频数据编码为MP3格式的Flutter插件,它集成了LAME MP3编码器的源代码,并在构建Flutter Runner时自动编译。与 dart_lame 不同,您不需要自己提供预编译的库文件。

使用方法

基本用法

下面是一个简单的示例,展示了如何使用 flutter_lame 将音频样本编码为MP3格式:

import 'dart:io';
import 'dart:typed_data';

final File f = File("output.mp3");
final IOSink sink = f.openWrite();
final LameMp3Encoder encoder = LameMp3Encoder(sampleRate: 44100, numChannels: 2);

Float64List leftChannelSamples;
Float64List rightChannelSamples;
// 获取样本数据,可以来自文件或麦克风

final mp3Frame = await encoder.encode(
  leftChannel: leftChannelSamples,
  rightChannel: rightChannelSamples);
sink.add(mp3Frame);
// 继续编码直到所有样本都处理完毕

// 最后,刷新编码器缓冲区
final lastMp3Frame = await encoder.flush();
sink.add(lastMp3Frame);

完整示例

以下是一个更完整的示例,展示了如何从WAV文件中读取音频数据并将其编码为MP3格式:

import 'dart:io';
import 'dart:async';
import 'dart:typed_data';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:path/path.dart' as path;
import 'package:flutter_lame/flutter_lame.dart';
import 'package:wav/wav.dart';

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

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

  [@override](/user/override)
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String? inputPath;
  String outputName = "output.mp3";
  bool working = false;

  void selectInputFile() async {
    final result = await FilePicker.platform.pickFiles(
        type: FileType.custom,
        dialogTitle: "Select WAV file",
        allowedExtensions: ["wav"],
        allowMultiple: false);

    if (result == null || result.paths.isEmpty) {
      return;
    }

    setState(() {
      inputPath = result.paths[0];
    });
  }

  void encodeMp3() async {
    if (inputPath == null) {
      throw StateError("inputPath should not be null");
    }

    final outputDir = await FilePicker.platform.getDirectoryPath(
        dialogTitle: "Pick a directory to save output MP3 file");
    if (outputDir == null) {
      return;
    }

    setState(() {
      working = true;
    });

    LameMp3Encoder? encoder;
    IOSink? sink;
    try {
      final wav = await compute(Wav.readFile, inputPath!);

      final File f = File(path.join(outputDir, outputName));
      sink = f.openWrite();
      encoder = LameMp3Encoder(
          sampleRate: wav.samplesPerSecond, numChannels: wav.channels.length);

      final left = wav.channels[0];
      Float64List? right;
      if (wav.channels.length > 1) {
        right = wav.channels[1];
      }

      for (int i = 0; i < left.length; i += wav.samplesPerSecond) {
        final mp3Frame = await encoder.encodeDouble(
            leftChannel: left.sublist(i, i + wav.samplesPerSecond),
            rightChannel: right?.sublist(i, i + wav.samplesPerSecond));
        sink.add(mp3Frame);
      }
      sink.add(await encoder.flush());
    } catch (e) {
      showDialog(
          context: context,
          builder: (context) => AlertDialog(
                title: const Text("Error"),
                content: Text(e.toString()),
              ));
    } finally {
      encoder?.close();
      sink?.close();
      setState(() {
        working = false;
      });
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    const textStyle = TextStyle(fontSize: 25);
    const spacerSmall = SizedBox(height: 10);
    const spacerLarge = SizedBox(height: 30);
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter LAME Example'),
        ),
        body: SingleChildScrollView(
          child: Container(
            padding: const EdgeInsets.all(10),
            child: Column(
              children: [
                const Text(
                  'Call LAME API through FFI that is shipped as source in the package. '
                  'The native code is built as part of the Flutter Runner build.',
                  style: textStyle,
                  textAlign: TextAlign.center,
                ),
                const Divider(),
                spacerLarge,
                ElevatedButton(
                    onPressed: !working ? selectInputFile : null,
                    child: const Text(
                      "Select WAV file",
                      style: textStyle,
                    )),
                spacerSmall,
                RichText(
                  text: TextSpan(
                      style: const TextStyle(fontSize: 25, color: Colors.black),
                      children: [
                        const TextSpan(
                            text: "Input WAV file: ",
                            style: TextStyle(fontWeight: FontWeight.bold)),
                        TextSpan(text: inputPath)
                      ]),
                  textAlign: TextAlign.center,
                ),
                spacerSmall,
                TextFormField(
                    onChanged: (v) => setState(() {
                          outputName = v;
                        }),
                    decoration:
                        const InputDecoration(labelText: "Output MP3 filename"),
                    initialValue: outputName),
                spacerSmall,
                ElevatedButton(
                    onPressed:
                        inputPath != null && outputName.isNotEmpty && !working
                            ? encodeMp3
                            : null,
                    child: const Text(
                      "Encode to MP3",
                      style: textStyle,
                    )),
                spacerSmall,
                if (working) const CircularProgressIndicator(),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

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

1 回复

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


当然,以下是一个关于如何使用 flutter_lame 插件进行音频编码的示例代码。flutter_lame 是一个用于 Flutter 的音频编码库,基于著名的 LAME MP3 编码器(libmp3lame)。请注意,在实际应用中,确保您已经按照 flutter_lame 的官方文档正确配置了插件。

首先,确保在您的 pubspec.yaml 文件中添加了 flutter_lame 依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_lame: ^最新版本号

然后,运行 flutter pub get 来获取依赖。

以下是一个简单的示例,演示如何使用 flutter_lame 将 WAV 文件编码为 MP3 文件:

import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_lame/flutter_lame.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter LAME Example'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: _encodeAudio,
            child: Text('Encode Audio'),
          ),
        ),
      ),
    );
  }

  Future<void> _encodeAudio() async {
    // 读取WAV文件
    final File wavFile = File('path/to/your/input.wav');
    final Uint8List wavData = await wavFile.readAsBytes();

    // 配置LAME编码器
    final LameEncoderConfig config = LameEncoderConfig(
      inSampleRate: 44100, // 输入采样率
      outSampleRate: 44100, // 输出采样率
      bitrate: 128, // 比特率(kbps)
      channels: 2, // 通道数(立体声)
      quality: LameQuality.VBR_QUALITY_0, // 质量模式(可变比特率)
    );

    // 创建LAME编码器实例
    final LameEncoder encoder = LameEncoder(config);

    // 编码音频
    try {
      final Uint8List mp3Data = await encoder.encode(wavData);

      // 保存MP3文件
      final File mp3File = File('path/to/your/output.mp3');
      await mp3File.writeAsBytes(mp3Data);

      print('Audio encoded successfully!');
    } catch (e) {
      print('Error encoding audio: $e');
    } finally {
      // 释放编码器资源
      encoder.dispose();
    }
  }
}

注意事项:

  1. 路径配置:确保 'path/to/your/input.wav''path/to/your/output.mp3' 路径正确,且应用有权限访问这些路径。
  2. 依赖配置:确保 flutter_lame 插件已正确安装和配置。
  3. 错误处理:在实际应用中,添加更多的错误处理逻辑以确保应用的健壮性。
  4. 平台特定配置flutter_lame 可能需要一些平台特定的配置(如 Android 的 NDK 版本),请查阅官方文档获取详细信息。

这个示例展示了如何使用 flutter_lame 插件将 WAV 文件编码为 MP3 文件。根据您的具体需求,您可能需要调整编码参数或处理输入/输出文件的逻辑。

回到顶部