amr_plugin 0.1.0 copy "amr_plugin: ^0.1.0" to clipboard
amr_plugin: ^0.1.0 copied to clipboard

A Flutter plugin that provides AMR (Adaptive Multi-Rate) audio format conversion capabilities for both iOS and Android platforms. Supports bidirectional conversion between AMR-NB/AMR-WB and WAV audio [...]

example/lib/main.dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:amr_plugin/amr_plugin.dart';
import 'package:audioplayers/audioplayers.dart';
import 'package:path_provider/path_provider.dart';
import 'package:http/http.dart' as http;

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

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _urlController = TextEditingController();
  String? _downloadedFilePath;
  String? _convertedFilePath;
  int? _downloadedFileSize;
  int? _convertedFileSize;
  String _status = '';
  bool _isConverting = false;
  bool _isWavToAmr = true;
  final AudioPlayer _audioPlayer = AudioPlayer();
  Map<String, dynamic>? _codecSupport;

  Future<void> _downloadFile(String url) async {
    setState(() {
      _status = '正在下载...';
      _downloadedFilePath = null;
      _convertedFilePath = null;
      _downloadedFileSize = null;
      _convertedFileSize = null;
    });
    try {
      final response = await http.get(Uri.parse(url));
      if (response.statusCode == 200) {
        final ext = url.toLowerCase().endsWith('.amr') ? 'amr' : 'wav';
        final dir = await getApplicationDocumentsDirectory();
        final file = File('${dir.path}/input.$ext');
        await file.writeAsBytes(response.bodyBytes);
        final fileSize = await file.length();
        setState(() {
          _downloadedFilePath = file.path;
          _downloadedFileSize = fileSize;
          _status = '下载完成: ${file.path} ($fileSize bytes)';
        });
      } else {
        setState(() {
          _status = '下载失败: ${response.statusCode}';
        });
      }
    } catch (e) {
      setState(() {
        _status = '下载异常: $e';
      });
    }
  }

  Future<void> _convert() async {
    if (_downloadedFilePath == null) return;
    setState(() {
      _isConverting = true;
      _status = '正在转换...';
      _convertedFilePath = null;
      _convertedFileSize = null;
    });
    try {
      String? resultPath;
      if (_isWavToAmr) {
        resultPath = await AmrPlugin.convertWavToAmr(_downloadedFilePath!, sampleRate: 8000, bitRate: 12200);
      } else {
        resultPath = await AmrPlugin.convertAmrToWav(_downloadedFilePath!, sampleRate: 8000);
      }
      if (resultPath != null) {
        final fileSize = await File(resultPath).length();
        setState(() {
          _convertedFilePath = resultPath;
          _convertedFileSize = fileSize;
          _status = '转换完成: $resultPath ($fileSize bytes)';
        });
      } else {
        setState(() {
          _status = '转换失败';
        });
      }
    } catch (e) {
      setState(() {
        _status = '转换异常: $e';
      });
    } finally {
      setState(() {
        _isConverting = false;
      });
    }
  }

  Future<void> _playConverted() async {
    if (_convertedFilePath == null) return;
    await _audioPlayer.stop();
    await _audioPlayer.play(DeviceFileSource(_convertedFilePath!));
  }

  Future<void> _uploadConvertedFile() async {
    if (_convertedFilePath == null) return;
    setState(() {
      _status = '正在上传...';
    });
    try {
      var uri = Uri.parse('http://192.168.1.58:8080/upload');
      var request = http.MultipartRequest('POST', uri);
      request.files.add(
        await http.MultipartFile.fromPath('file', _convertedFilePath!),
      );
      var response = await request.send();
      if (response.statusCode == 200) {
        final respStr = await response.stream.bytesToString();
        setState(() {
          _status = '上传成功: $respStr';
        });
      } else {
        setState(() {
          _status = '上传失败: \\${response.statusCode}';
        });
      }
    } catch (e) {
      setState(() {
        _status = '上传异常: $e';
      });
    }
  }

  Future<void> _testCodecSupport() async {
    setState(() {
      _status = '正在测试MediaCodec支持...';
    });
    try {
      final support = await AmrPlugin.testMediaCodecSupport();
      setState(() {
        _codecSupport = support;
        if (support != null) {
          final supportList = support.entries
              .map((e) => '${e.key}: ${e.value ? '✅' : '❌'}')
              .join('\n');
          _status = 'MediaCodec支持测试完成:\n$supportList';
        } else {
          _status = 'MediaCodec支持测试失败';
        }
      });
    } catch (e) {
      setState(() {
        _status = 'MediaCodec测试异常: $e';
      });
    }
  }

  @override
  void dispose() {
    _audioPlayer.dispose();
    _urlController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('AMR/WAV 转换与播放 Demo'),
        ),
        body: SingleChildScrollView(child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              TextField(
                controller: _urlController,
                decoration: const InputDecoration(
                  labelText: '输入 wav/amr 文件的 URL',
                  border: OutlineInputBorder(),
                ),
              ),
              const SizedBox(height: 12),
              Row(
                children: [
                  Expanded(
                    child: ElevatedButton(
                      onPressed: () {
                        if (_urlController.text.isNotEmpty) {
                          _downloadFile(_urlController.text);
                        }
                      },
                      child: const Text('下载'),
                    ),
                  ),
                  const SizedBox(width: 12),
                  Expanded(
                    child: DropdownButton<bool>(
                      value: _isWavToAmr,
                      items: const [
                        DropdownMenuItem(value: true, child: Text('WAV → AMR')),
                        DropdownMenuItem(value: false, child: Text('AMR → WAV')),
                      ],
                      onChanged: (v) {
                        setState(() {
                          _isWavToAmr = v ?? true;
                        });
                      },
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 12),
              Visibility(child: ElevatedButton(
                onPressed: _testCodecSupport,
                child: const Text('测试MediaCodec支持'),
              ), visible: false),
              const SizedBox(height: 12),
              ElevatedButton(
                onPressed: (_downloadedFilePath != null && !_isConverting)
                    ? _convert
                    : null,
                child: _isConverting ? const CircularProgressIndicator() : const Text('转换'),
              ),
              const SizedBox(height: 12),
              if (_convertedFilePath != null)
                ElevatedButton(
                  onPressed: _playConverted,
                  child: const Text('播放转换后文件'),
                ),
              if (_convertedFilePath != null)
                ElevatedButton(
                  onPressed: _uploadConvertedFile,
                  child: const Text('上传转换后文件'),
                ),
              const SizedBox(height: 12),
              Container(
                padding: const EdgeInsets.all(8),
                decoration: BoxDecoration(
                  border: Border.all(color: Colors.grey),
                  borderRadius: BorderRadius.circular(4),
                ),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const Text('状态信息:', style: TextStyle(fontWeight: FontWeight.bold)),
                    const SizedBox(height: 4),
                    Text(_status),
                    if (_downloadedFilePath != null) ...[
                      const SizedBox(height: 8),
                      Text('下载文件: $_downloadedFilePath'),
                      Text('下载文件大小: ${_downloadedFileSize ?? '-'} bytes'),
                    ],
                    if (_convertedFilePath != null) ...[
                      const SizedBox(height: 8),
                      Text('转换后文件: $_convertedFilePath'),
                      Text('转换后文件大小: ${_convertedFileSize ?? '-'} bytes'),
                    ],
                    if (_codecSupport != null) ...[
                      const SizedBox(height: 8),
                      const Text('MediaCodec支持情况:', style: TextStyle(fontWeight: FontWeight.bold)),
                      for (final entry in _codecSupport!.entries)
                        Text('${entry.key}: ${entry.value ? '✅ 支持' : '❌ 不支持'}'),
                    ],
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    )
    );
  }
}
3
likes
135
points
46
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter plugin that provides AMR (Adaptive Multi-Rate) audio format conversion capabilities for both iOS and Android platforms. Supports bidirectional conversion between AMR-NB/AMR-WB and WAV audio formats with advanced audio processing.

Repository (GitHub)
View/report issues

Topics

#audio #amr #wav #codec #converter

Documentation

Documentation
API reference

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on amr_plugin

Packages that implement amr_plugin