패키지, 저장소 및 앱 카테고리 검색

waveform_recorder 표지
패키지 상세v2.0.0

waveform_recorder

실시간 파형 시각화 기능을 갖춘 오디오 녹음용 플러터 패키지로, 채팅 애플리케이션의 음성 메시징 및 오디오 녹음 기능에 적합합니다.

AndroidiOSWebmacOSWindowsLinux
30일 다운로드
1.7만
좋아요
53
Pub 점수
160

패키지 설치

flutter pub add waveform_recorder

패키지 개요

공개 정보를 바탕으로 생성한 선택 가이드입니다.

실시간 파형 시각화를 통해 오디오 녹음을 가능하게 하는 플러터 패키지로, 음성 메시지 또는 오디오 입력 기능이 필요한 애플리케이션을 위한 것입니다. 안드로이드, iOS, 웹, 맥OS, 윈도우, 리눅스 등 여러 플랫폼을 지원하며, 녹음 중 시각적 피드백을 제공하는 원활한 사용자 경험을 제공합니다. 채팅이나 커뮤니케이션 앱에 쉽게 통합되어 사용자가 말할 때 자신의 음성 파형을 볼 수 있도록 합니다. 성능과 크로스플랫폼 일관성을 고려해 제작되었으며, 최소한의 설정으로 오디오 녹음 기능 구현을 간단하게 만듭니다.

사용 사례

  • 채팅 앱에서의 음성 메시지
  • 오디오 노트 작성
  • 실시간 음성 피드백
  • 팟캐스트 녹음 인터페이스
  • 음성 기반의 인터랙티브 게임
  • 라이브 오디오 스트리밍 미리보기

주요 기능

  • 실시간 파형 시각화
  • 크로스 플랫폼 지원
  • 기록용 간단한 API
  • 녹화 중 시각 피드백
  • 저지연 오디오 처리
  • 내장 재생 컨트롤

적합한 대상

  • 채팅 애플리케이션을 개발하는 개발자
  • 음성 기능을 갖춘 도구의 제작자
  • 음성 입력 기능이 있는 교육용 앱
  • 오디오 녹음 프로토타입
  • 직관적인 오디오 UI가 필요한 앱

고려 사항

  • 모든 플랫폼에서 마이크 권한이 필요합니다
  • 웹 지원에는 브라우저 제한이 있을 수 있습니다
  • 큰 녹음은 메모리 사용량에 영향을 줄 수 있습니다
  • 저사양 기기에서는 성능이 다를 수 있습니다
  • 파형 모양의 사용자 정의가 제한됨
  • 기반 플랫폼 오디오 API에 따라 다름

원본 README

연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.

The waveform_recorder package provides a widget to show a waveform as an audio stream is being recorded in the style of recent AI chat packages.

Screenshot of waveform_recorder in
action

Setup

For this package to work, you'll need to set up the underlying record package according to the setup and permission instructions.

Usage

The main entry point for this package is the WaveformRecorder widget, which requires an instance of the WaveformRecorderController to start/stop recording. Here's an example of using the recorder to record audio and then allowing the user to play it back:

import 'dart:async';

import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:waveform_recorder/waveform_recorder.dart';

void main() => runApp(const MyApp());

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

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

class _MyAppState extends State<MyApp> {
  final _textController = TextEditingController();
  final _waveController = WaveformRecorderController();

  @override
  void dispose() {
    _textController.dispose();
    _waveController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) => MaterialApp(
        home: Scaffold(
          appBar: AppBar(title: const Text('WaveForm Example')),
          body: ListenableBuilder(
            listenable: _waveController,
            builder: (context, _) => Column(
              children: [
                Expanded(
                  child: Center(
                    child: OutlinedButton(
                      onPressed: !_waveController.isRecording &&
                              _waveController.file != null
                          ? _playRecording
                          : null,
                      child: const Text('Play'),
                    ),
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.all(16),
                  child: Row(
                    children: [
                      Expanded(
                        child: DecoratedBox(
                          decoration: BoxDecoration(
                            border: Border.all(color: Colors.grey),
                            borderRadius: BorderRadius.circular(8),
                          ),
                          child: _waveController.isRecording
                              ? WaveformRecorder(
                                  height: 48,
                                  controller: _waveController,
                                  onRecordingStopped: _onRecordingStopped,
                                )
                              : TextField(
                                  controller: _textController,
                                  maxLines: 1,
                                  decoration: const InputDecoration(
                                    border: InputBorder.none,
                                    contentPadding: EdgeInsets.symmetric(
                                      horizontal: 8,
                                    ),
                                  ),
                                ),
                        ),
                      ),
                      const Gap(8),
                      IconButton(
                        icon: Icon(
                          _waveController.isRecording ? Icons.stop : Icons.mic,
                        ),
                        onPressed: _toggleRecording,
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      );

  Future<void> _toggleRecording() => switch (_waveController.isRecording) {
        true => _waveController.stopRecording(),
        false => _waveController.startRecording(),
      };

  Future<void> _onRecordingStopped() async {
    final file = _waveController.file;
    if (file == null) return;

    _textController.text = ''
        '${file.name}: '
        '${_waveController.length.inMilliseconds / 1000} seconds';

    debugPrint('XFile properties:');
    debugPrint('  path: ${file.path}');
    debugPrint('  name: ${file.name}');
    debugPrint('  mimeType: ${file.mimeType}');
  }

  Future<void> _playRecording() async {
    final file = _waveController.file;
    if (file == null) return;
    final source = kIsWeb ? UrlSource(file.path) : DeviceFileSource(file.path);
    await AudioPlayer().play(source);
  }
}
Usage Considerations

For all platforms except the web, the output of a record operation is a file on your hard drive; it's your app's responsibility to remove this temp file when it's done with it. When executing on the web, the file (an instance of the XFile type from the cross_file package) of the recorded audio will contain a path to a blob URL but otherwise, it will be a file in the file system. You can get the path to that file from WaveformRecorderController.file.path, e.g.

  Future<void> _deleteRecording() async {
    final file = _waveController.file;
    if (file == null) return;
    if (!kIsWeb) await File(file.path).delete();
  }

Feedback

Your feedback via issues or PRs is welcome!

카테고리

의존성

의존성 목록 6 개

소스 저장소

이 패키지를 사용하는 프로젝트