Flutter音频裁剪插件flutter_audio_cutter的使用

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

Flutter音频裁剪插件flutter_audio_cutter的使用

flutter_audio_cutter 是一个用于从音频文件中剪辑出一段音频的插件,目前支持Android平台。

开始使用

添加依赖

pubspec.yaml 文件中添加 flutter_audio_cutter 依赖:

dependencies:
  flutter_audio_cutter: ^1.0.3+1

配置Android SDK版本

由于 flutter_audio_cutter 使用了 ffmpeg_kit_flutter 包,该包需要较高的Android SDK版本。因此,请修改你的 build.gradle (app) 文件以避免错误:

defaultConfig {
  ...
  minSdkVersion 24
  ...
}

使用方法

AudioCutter.cutAudio(...) 方法会返回剪辑后的音频文件路径。

import 'package:flutter_audio_cutter/audio_cutter.dart';

// 剪辑开始时间(秒)
var startPoint = 15.0; 
// 剪辑结束时间(秒)
var endPoint = 45.0; 
// 要剪辑的音频文件路径
var pathToFile = 'path/to/audio-file.mp3'; 

// 调用剪辑方法
var result = await AudioCutter.cutAudio(pathToFile, startPoint, endPoint);

示例代码

以下是完整的示例代码,展示了如何使用 flutter_audio_cutter 插件来选择音频文件并进行剪辑。

import 'dart:io';

import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_audio_cutter/audio_cutter.dart';
import 'package:just_audio/just_audio.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Audio Cutter Example',
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  [@override](/user/override)
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  String inputFileView = '输入文件路径';
  File inputFile = File('');
  File outputFile = File('');
  RangeValues cutValues = const RangeValues(0, 5);
  int timeFile = 10;
  final player = AudioPlayer();
  final outputPlayer = AudioPlayer();
  bool previewPlay = false;
  bool outputPlay = false;
  bool isCutting = false;
  bool isCut = false;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('音频剪辑示例'),
      ),
      body: Center(
        child: SingleChildScrollView(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Text(
                '输入',
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
              Text(
                inputFileView,
                textAlign: TextAlign.center,
              ),
              MaterialButton(
                onPressed: _onPickFile,
                color: Colors.blue,
                child: const Text('选择文件'),
              ),
              const Divider(),
              const Text(
                '剪切',
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
              RangeSlider(
                  values: cutValues,
                  max: timeFile.toDouble(),
                  divisions: timeFile,
                  labels: RangeLabels(
                      _getViewTimeFromCut(cutValues.start.toInt()).toString(),
                      _getViewTimeFromCut(cutValues.end.toInt()).toString()),
                  onChanged: (values) {
                    setState(() => cutValues = values);
                    player.seek(Duration(seconds: cutValues.start.toInt()));
                  }),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: [
                  Text('开始: ${_getViewTimeFromCut(cutValues.start.toInt())}'),
                  Text('结束: ${_getViewTimeFromCut(cutValues.end.toInt())}'),
                ],
              ),
              IconButton(
                  onPressed: _onPlayPreview,
                  icon:
                      Icon(previewPlay ? Icons.stop_circle : Icons.play_arrow)),
              MaterialButton(
                onPressed: _onCut,
                color: Colors.blue,
                child: const Text('剪切'),
              ),
              const Divider(),
              const Text(
                '输出',
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
              isCutting
                  ? Column(
                      children: const [
                        CircularProgressIndicator(),
                        Text('等待...')
                      ],
                    )
                  : Column(
                      children: [
                        Text(isCut ? '完成!' : ''),
                        Text(isCut ? outputFile.path : '输出文件路径'),
                        Text(
                            '时长: ${outputPlayer.duration?.inMinutes ?? 0}:${outputPlayer.duration?.inSeconds ?? 0}'),
                        IconButton(
                            onPressed: _onOutputPlayPreview,
                            icon: Icon(outputPlay
                                ? Icons.stop_circle
                                : Icons.play_arrow)),
                      ],
                    )
            ],
          ),
        ),
      ),
    );
  }

  Future<void> _onPickFile() async {
    FilePickerResult? result = await FilePicker.platform.pickFiles(
      type: FileType.custom,
      allowedExtensions: ['mp3'],
    );
    if (result != null) {
      inputFile = File(result.files.single.path!);
      await player.setFilePath(inputFile.path);
      setState(() {
        timeFile = player.duration!.inSeconds;
        cutValues = RangeValues(0, timeFile.toDouble());
        inputFileView = inputFile.path;
      });
    }
  }

  _getViewTimeFromCut(int index) {
    int minute = index ~/ 60;
    int second = index - minute * 60;
    return "$minute:$second";
  }

  void _onPlayPreview() {
    if (inputFile.path != '') {
      setState(() => previewPlay = !previewPlay);
      if (player.playing) {
        player.stop();
      } else {
        player.seek(Duration(seconds: cutValues.start.toInt()));
        player.play();
      }
    }
  }

  Future<void> _onCut() async {
    if (inputFile.path != '') {
      setState(() => isCutting = true);
      var result = await AudioCutter.cutAudio(
          inputFile.path, cutValues.start, cutValues.end);
      outputFile = File(result);
      await outputPlayer.setFilePath(result);
      setState(() {
        isCut = true;
        isCutting = false;
      });
    }
  }

  void _onOutputPlayPreview() {
    if (outputFile.path != '') {
      setState(() => outputPlay = !outputPlay);
      if (outputPlayer.playing) {
        print("停止");
        outputPlayer.stop();
      } else {
        print("播放");
        outputPlayer.play();
      }
    }
  }
}

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

1 回复

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


当然,下面是一个关于如何使用Flutter音频裁剪插件flutter_audio_cutter的代码示例。这个示例将展示如何集成和使用该插件来裁剪音频文件。

首先,确保你已经在pubspec.yaml文件中添加了flutter_audio_cutter依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_audio_cutter: ^最新版本号  # 请替换为最新的版本号

然后,运行flutter pub get来安装依赖。

接下来,在你的Flutter应用中,你可以按照以下步骤使用flutter_audio_cutter

  1. 导入插件

在你的Dart文件中导入flutter_audio_cutter插件:

import 'package:flutter_audio_cutter/flutter_audio_cutter.dart';
  1. 请求权限(如果需要):

如果你的应用需要在Android上访问存储,你需要在AndroidManifest.xml中添加相关权限,并在运行时请求这些权限。对于iOS,你需要在Info.plist中添加相应的权限描述。

  1. 使用插件裁剪音频

下面是一个简单的示例,展示如何使用flutter_audio_cutter来裁剪音频文件:

import 'package:flutter/material.dart';
import 'package:flutter_audio_cutter/flutter_audio_cutter.dart';
import 'dart:io';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  File? _originalAudioFile;
  File? _trimmedAudioFile;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Audio Cutter Example'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            children: [
              _buildAudioPicker(),
              SizedBox(height: 20),
              _buildTrimButton(),
              SizedBox(height: 20),
              _buildResult(),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildAudioPicker() {
    return ElevatedButton(
      onPressed: () async {
        FilePickerResult? result = await FilePicker.platform.pickFiles(
          type: FileType.audio,
        );

        if (result != null && result.files.isNotEmpty) {
          File file = File(result.files.first.path!);
          setState(() {
            _originalAudioFile = file;
            _trimmedAudioFile = null;
          });
        }
      },
      child: Text('Pick Audio File'),
    );
  }

  Widget _buildTrimButton() {
    if (_originalAudioFile == null) {
      return Container();
    }

    return ElevatedButton(
      onPressed: () async {
        double startTime = 5.0; // 开始时间(秒)
        double endTime = 15.0;  // 结束时间(秒)

        try {
          _trimmedAudioFile = await FlutterAudioCutter.cutAudio(
            sourcePath: _originalAudioFile!.path,
            startTime: startTime,
            endTime: endTime,
          );

          print('Trimmed audio file saved at: ${_trimmedAudioFile!.path}');
        } catch (e) {
          print('Error cutting audio: $e');
        }
      },
      child: Text('Trim Audio'),
    );
  }

  Widget _buildResult() {
    if (_trimmedAudioFile == null) {
      return Text('No trimmed audio file available.');
    } else {
      return Column(
        children: [
          Text('Trimmed Audio File Path: ${_trimmedAudioFile!.path}'),
          SizedBox(height: 10),
          ElevatedButton(
            onPressed: () async {
              // 这里可以添加播放裁剪后音频的逻辑,例如使用audio_players插件
              // 或者简单地让用户知道他们可以通过文件管理器访问该文件
              print('Play trimmed audio or handle the file as needed.');
            },
            child: Text('Play Trimmed Audio'),
          ),
        ],
      );
    }
  }
}

请注意,这个示例使用了file_picker插件来选择音频文件。你需要在pubspec.yaml中添加file_picker依赖,并运行flutter pub get来安装它。

这个示例展示了如何选择一个音频文件,然后裁剪该文件的一个特定时间段,并显示裁剪后的文件路径。你可以根据需要扩展这个示例,例如添加错误处理、UI改进或集成音频播放功能。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!