Un package Flutter pour un ajustement audio facile
Caractéristiques
- Tondeuse audio personnalisable.
- Contrôle de la lecture audio.
- Récupération et stockage du fichier audio.
Exemple
Le exemple d’application fonctionnant sur Android OnePlus 7 :
Usage
Ajouter la dépendance easy_audio_trimmer
à ton pubspec.yaml dossier:
dependencies:
easy_audio_trimmer: ^1.0.0
Paramétrage Androïd
Aucune configuration supplémentaire n’est nécessaire pour une utilisation sur la plate-forme Android. Tu es prêt!
Paramétrage iOS
Version FFmpeg
Ce paquet utilise Version LTS de la mise en œuvre de FFmpeg.
Version LTS | |
---|---|
Niveau d’API Android | 16 |
Accès à la caméra Android | – |
Architectures Android | bras-v7aarm-v7a-neonarm64-v8ax86x86-64 |
SDK mini iOS | dix |
Architectures iOS | armv7arm64i386x86-64 |
Fonctionnalités
Chargement du fichier audio d’entrée
final Trimmer _trimmer = Trimmer();
await _trimmer.loadAudio(audioFile: widget.file);
Enregistrement de l’audio coupé
Renvoie une chaîne pour indiquer si l’opération d’enregistrement a réussi.
_trimmer.saveTrimmedAudio(
startValue: _startValue,
endValue: _endValue,
audioFileName: DateTime.now().millisecondsSinceEpoch.toString(),
onSave: (outputPath) {
setState(() {
_progressVisibility = false;
});
debugPrint('OUTPUT PATH: $outputPath');
},
);
État de la lecture audio
Renvoie l’état de la lecture audio. Si vrai alors l’audio est en cours de lecture, sinon il est mis en pause.
await _trimmer.audioPlaybackControl(
startValue: _startValue,
endValue: _endValue,
);
Widget
Afficher la zone de découpage audio
TrimViewer(
trimmer: _trimmer,
viewerHeight: 50.0,
viewerWidth: MediaQuery.of(context).size.width,
maxAudioLength: const Duration(seconds: 10),
onChangeStart: (value) => _startValue = value,
onChangeEnd: (value) => _endValue = value,
allowAudioSelection: true,
onChangePlaybackState: (value) =>
setState(() => _isPlaying = value),
)
Exemple
Avant d’utiliser cet exemple directement dans une application Flutter, n’oubliez pas d’ajouter le easy_audio_trimmer
& file_picker
colis à votre pubspec.yaml
dossier.
Vous pouvez essayer cet exemple en remplaçant tout le contenu de main.dart
fichier d’un projet Flutter nouvellement créé.
import 'dart:io';
import 'package:example/trimmer_view.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: createMaterialColor(const Color(0xFF332FD0)),
),
home: const FileSelectorWidget());
}
}
class FileSelectorWidget extends StatefulWidget {
const FileSelectorWidget({super.key});
@override
State<FileSelectorWidget> createState() => _FileSelectorWidgetState();
}
class _FileSelectorWidgetState extends State<FileSelectorWidget> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Audio Trimmer"),
),
body: Center(
child: ElevatedButton(
onPressed: () async {
FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.audio,
allowCompression: false,
);
if (result != null) {
File file = File(result.files.single.path!);
// ignore: use_build_context_synchronously
Navigator.of(context).push(
MaterialPageRoute(builder: (context) {
return AudioTrimmerView(file);
}),
);
}
},
child: const Text("Select File")),
),
);
}
}
class AudioTrimmerView extends StatefulWidget {
final File file;
const AudioTrimmerView(this.file, {Key? key}) : super(key: key);
@override
State<AudioTrimmerView> createState() => _AudioTrimmerViewState();
}
class _AudioTrimmerViewState extends State<AudioTrimmerView> {
final Trimmer _trimmer = Trimmer();
double _startValue = 0.0;
double _endValue = 0.0;
bool _isPlaying = false;
bool _progressVisibility = false;
bool isLoading = false;
@override
void initState() {
super.initState();
_loadAudio();
}
void _loadAudio() async {
setState(() {
isLoading = true;
});
await _trimmer.loadAudio(audioFile: widget.file);
setState(() {
isLoading = false;
});
}
_saveAudio() {
setState(() {
_progressVisibility = true;
});
_trimmer.saveTrimmedAudio(
startValue: _startValue,
endValue: _endValue,
audioFileName: DateTime.now().millisecondsSinceEpoch.toString(),
onSave: (outputPath) {
setState(() {
_progressVisibility = false;
});
debugPrint('OUTPUT PATH: $outputPath');
},
);
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
if (Navigator.of(context).userGestureInProgress) {
return false;
} else {
return true;
}
},
child: Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: const Text("Audio Trimmer"),
),
body: isLoading
? const CircularProgressIndicator()
: Center(
child: Container(
padding: const EdgeInsets.only(bottom: 30.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Visibility(
visible: _progressVisibility,
child: LinearProgressIndicator(
backgroundColor:
Theme.of(context).primaryColor.withOpacity(0.5),
),
),
ElevatedButton(
onPressed:
_progressVisibility ? null : () => _saveAudio(),
child: const Text("SAVE"),
),
AudioViewer(trimmer: _trimmer),
Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TrimViewer(
trimmer: _trimmer,
viewerHeight: 100,
viewerWidth: MediaQuery.of(context).size.width,
durationStyle: DurationStyle.FORMAT_MM_SS,
backgroundColor: Theme.of(context).primaryColor,
barColor: Colors.white,
durationTextStyle: TextStyle(
color: Theme.of(context).primaryColor),
allowAudioSelection: true,
editorProperties: TrimEditorProperties(
circleSize: 10,
borderPaintColor: Colors.pink,
borderWidth: 4,
borderRadius: 5,
circlePaintColor: Colors.pink.shade800,
),
areaProperties:
TrimAreaProperties.edgeBlur(blurEdges: true),
onChangeStart: (value) => _startValue = value,
onChangeEnd: (value) => _endValue = value,
onChangePlaybackState: (value) {
if (mounted) {
setState(() => _isPlaying = value);
}
},
),
),
),
TextButton(
child: _isPlaying
? Icon(
Icons.pause,
size: 80.0,
color: Theme.of(context).primaryColor,
)
: Icon(
Icons.play_arrow,
size: 80.0,
color: Theme.of(context).primaryColor,
),
onPressed: () async {
bool playbackState =
await _trimmer.audioPlaybackControl(
startValue: _startValue,
endValue: _endValue,
);
setState(() => _isPlaying = playbackState);
},
)
],
),
),
),
),
);
}
}
Dépannage
Lors de l’exécution sur la plate-forme Android, s’il donne une erreur que le minSdkVersion
doit être 24
ou sur la plate-forme iOS que la version de la plate-forme Podfile doit être 11
allez d’abord à pubspec.lock
fichier et voir si la version de ffmpeg_kit_flutter
a -LTS
suffixe. Cela devrait résoudre tous les problèmes de la plate-forme iOS.
Sur Android, si vous rencontrez toujours le même problème, essayez d’ajouter ce qui suit au <project_directory>/android/app/src/main/AndroidManifest.xml
:
<manifest xmlns:tools=" ....... >
<uses-sdk tools:overrideLibrary="com.arthenica.ffmpegkit.flutter, com.arthenica.ffmpegkit" />
</manifest>
Licence
Copyright (c) 2022 Mayur Pitroda
L’autorisation est accordée, gratuitement, à toute personne obtenant une copie de ce logiciel et des fichiers de documentation associés (le « Logiciel »), de traiter le Logiciel sans restriction, y compris, sans limitation, les droits d’utilisation, de copie, de modification, de fusion , publier, distribuer, sous-licencier et/ou vendre des copies du Logiciel, et permettre aux personnes à qui le Logiciel est fourni de le faire, sous réserve des conditions suivantes :
L’avis de droit d’auteur ci-dessus et cet avis d’autorisation doivent être inclus dans toutes les copies ou parties substantielles du Logiciel.
LE LOGICIEL EST FOURNI « EN L’ÉTAT », SANS GARANTIE D’AUCUNE SORTE, EXPLICITE OU IMPLICITE, Y COMPRIS, MAIS SANS S’Y LIMITER, LES GARANTIES DE QUALITÉ MARCHANDE, D’ADÉQUATION À UN USAGE PARTICULIER ET D’ABSENCE DE CONTREFAÇON. EN AUCUN CAS, LES AUTEURS OU LES DÉTENTEURS DU COPYRIGHT NE SERONT RESPONSABLES DE TOUTE RÉCLAMATION, DOMMAGE OU AUTRE RESPONSABILITÉ, QUE CE SOIT DANS UNE ACTION CONTRACTUELLE, DÉLICTUELLE OU AUTRE, DÉCOULANT DE, DE OU EN RELATION AVEC LE LOGICIEL OU L’UTILISATION OU D’AUTRES OPÉRATIONS DANS LE LOGICIEL.
GitHub
Voir Github