-
Flutter Sound user: your documentation is there
canardoux / flutter_sound Goto Github PK
View Code? Open in Web Editor NEWFlutter plugin for sound. Audio recorder and player.
License: Mozilla Public License 2.0
Flutter plugin for sound. Audio recorder and player.
License: Mozilla Public License 2.0
The example provided it the README and the pub page for start recording is wrong. It is the same as start player example. Can you please correct it.
flutter_sound: ^1.3.4
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel dev, v1.3.8, on Mac OS X 10.13.6 17G65, locale en-AR)
[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
[✓] iOS toolchain - develop for iOS devices (Xcode 10.1)
[✓] Android Studio
[✓] Android Studio (version 3.3)
[✓] IntelliJ IDEA Community Edition (version 2018.3.5)
[✓] VS Code (version 1.31.1)
[✓] VS Code (version 1.26.0)
[✓] Connected device (1 available)
IOS
Emulator
String path = await flutterSound.startRecorder(null);
*** First throw call stack:
(
0 CoreFoundation 0x000000010916729b __exceptionPreprocess + 331
1 libobjc.A.dylib 0x0000000108703735 objc_exception_throw + 48
2 CoreFoundation 0x0000000109185fa4 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
3 CoreFoundation 0x000000010916bfb6 forwarding + 1446
4 CoreFoundation 0x000000010916de88 _CF_forwarding_prep_0 + 120
5 flutter_sound 0x000000010693d85b -[FlutterSoundPlugin startRecorder:::::result:] + 1163
6 flutter_sound 0x000000010693c823 -[FlutterSoundPlugin handleMethodCall:result:] + 1043
7 Flutter 0x0000000103cc96da __45-[FlutterMethodChannel setMethodCallHandler:]_block_invoke + 115
8 Flutt<…>
Lost connection to device.
To move forward support for AndroidX will be great.
1.2.1
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.0.0, on Mac OS X 10.14.2 18C54, locale en-GB)
[✓] Android toolchain - develop for Android devices (Android SDK 28.0.3)
[✓] iOS toolchain - develop for iOS devices (Xcode 10.1)
[✓] Android Studio (version 3.1)
[✓] IntelliJ IDEA Community Edition (version 2018.2.3)
[✓] VS Code (version 1.30.2)
[✓] Connected device (2 available)
iOS
Expect startPlayer to not append a tmp folder to the path supplied.
Tmp folder is appended to the path supplied - issue is in iOS. In Android it works correctly.
iOS X , iOS 8,7, iphone SE + Live devices for the same
Supply a path to startPlayer.
I have supplied two screenshots that shows the place in iOS which is incorrect. In Android you handle this correctly and do not append a tmp folder.
I have created an AudioView widget that encapsulates the Flutter Sound functionality - in the constructor we can go into automatic play mode if playerBytes is not null. In which case we take the bytes passed to this class and write out in a temp folder - the workaround in iOS is not to set the path to _tuple.playbackFile:
AudioView(
{this.playerMode = false, this.playerBytes, this.autoPlay = false}) {
/// If we want to display the audio and operate in playback mode ...
if (playerBytes != null) {
var tmp = Directory.systemTemp;
String fileExtension;
print(tmp.path);
debug('--Player to play sound file--');
if (defaultTargetPlatform == TargetPlatform.android) {
debug('Android');
fileExtension = 'mp4';
} else if (defaultTargetPlatform == TargetPlatform.iOS) {
debug('iOS');
fileExtension = 'm4a';
} else {
debug(defaultTargetPlatform.toString());
fileExtension = 'm4a';
// just set to m4a
}
File f = File('${tmp.path}/playback2.$fileExtension');
debug('New file = ${f.path}');
f.writeAsBytesSync(playerBytes);
// the iOS version of the Flutter sound adds the temp folder - so we just need to supply the file
if (defaultTargetPlatform == TargetPlatform.iOS) {
_tuple.playbackFile = 'playback2.$fileExtension';
} else {
_tuple.playbackFile = '${f.uri}';
}
} else {
_tuple.playbackFile = null;
}
}
Need the ability to determine the current recording level
ios - peakpowerforchannel
android - https://goo.gl/teko1u
Someone suggested that you add a license !
Thanks
flutter_sound v1.2.4
when call this function in ios, the para uri will be file name but not the file uri
flutter_sound: ^1.0.6
[√] Flutter (Channel stable, v1.0.0, on Microsoft Windows [versão 10.0.17134.523], locale pt-BR)
[√] Android toolchain - develop for Android devices (Android SDK 28.0.3)
[√] Android Studio (version 3.2)
[√] IntelliJ IDEA Community Edition (version 2018.3)
[√] Connected device (1 available)
• No issues found!
Android
Save file as *.mp3
File is saved as *.mp4, if i change to *.mp3 renaming the file, playing it works (with an audio player app)
Real device. Alcatel 5085N A5 Android 6
Just follow the docs to start and stop the recorder, then test the code and see the file in the folder.
I'm getting this error while trying to use flutter_sound. All others permissions are granted right, but "WRITE_EXTERNAL_STORAGE", it says:
I/flutter (18339): startRecorder error: Exception:
PlatformException(FlutterSoundPlugin, NO PERMISSION GRANTED,
android.permission.RECORD_AUDIO or android.permission.WRITE_EXTERNAL_STORAGE)
D/AndroidRuntime(18339): Shutting down VM
E/AndroidRuntime(18339): FATAL EXCEPTION: main
E/AndroidRuntime(18339): Process: com.example.nw, PID: 18339
E/AndroidRuntime(18339): java.lang.RuntimeException: Failure delivering result
ResultInfo{who=@android:requestPermissions:, request=0, result=-1, data=Intent {
act=android.content.pm.action.REQUEST_PERMISSIONS
VirtualScreenParam=Params{mDisplayId=-1, null, mFlags=0x00000000)} (has extras)
}} to activity {com.example.nw/com.example.nw.MainActivity}:
java.lang.IllegalStateException: Reply already submitted
I've already tried append tools:remove="androidSdkVersion"
or tools:node="replace"
to uses-permission
in AndroidManifest.xml.
I want get a wav recorder.Do you have any plans?
1.3.1
Real device - Mi Note 4
Audio stop when app closes
Audio is still playing in background
Real device
1.1.4
[✓] Flutter (Channel beta, v0.9.4, on Mac OS X 10.14 18A391, locale en-RU)
[✓] Android toolchain - develop for Android devices (Android SDK 27.0.3)
[✓] iOS toolchain - develop for iOS devices (Xcode 10.0)
[✓] Android Studio (version 3.1)
[✓] VS Code (version 1.28.2)
[✓] Connected devices (1 available)
• No issues found!
iOS
I expect that when I tap on a mic icon every time I'll record new audio. After tap on a play button and I will listen the new recorded audio file.
But every time I record a new audio, I still play first recorded audio file.
Real Device
Tap a mic - record an audio
Tap a play button - listen what I recorded
Tap the mic button again to record new audio
Wanna hear that new audio, but I still hear first one.
import 'package:flutter/material.dart';
import 'package:intl/intl.dart' show DateFormat;
import 'dart:io';
import 'dart:async';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:path_provider/path_provider.dart';
class AudioRecordPage extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<AudioRecordPage> {
bool _isRecording = false;
bool _isPlaying = false;
StreamSubscription _recorderSubscription;
StreamSubscription _playerSubscription;
FlutterSound flutterSound;
String _recorderTxt = '00:00:00';
String _playerTxt = '00:00:00';
String _audioFileName;
String _recordedFilePath;
@override
void initState() {
super.initState();
_initSound();
}
@override
void dispose() {
_recorderSubscription?.cancel();
_recorderSubscription = null;
_playerSubscription?.cancel();
_playerSubscription = null;
flutterSound = null;
super.dispose();
}
_initSound() {
flutterSound = FlutterSound();
flutterSound.setSubscriptionDuration(0.01);
}
void startRecorder() async {
// delete previous
if (_recordedFilePath != null) {
final f = File(_recordedFilePath);
if (await f.exists()) {
await File(_recordedFilePath).delete();
print('Preview has been deleted $_audioFileName');
}
}
try {
final ms = DateTime.now().millisecondsSinceEpoch.toString();
final audioFileName = '$ms-audio.m4a';
final path = await flutterSound.startRecorder(audioFileName);
print('startRecorder: $path');
_recorderSubscription = flutterSound.onRecorderStateChanged.listen((e) {
DateTime date =
new DateTime.fromMillisecondsSinceEpoch(e.currentPosition.toInt());
String txt = DateFormat('mm:ss:SS', 'en_US').format(date);
this.setState(() {
this._recorderTxt = txt.substring(0, 8);
});
});
this.setState(() {
this._audioFileName = audioFileName;
this._recordedFilePath = null;
this._isRecording = true;
});
} catch (err) {
print('startRecorder error: $err');
}
}
void stopRecorder() async {
try {
String result = await flutterSound.stopRecorder();
print('stopRecorder: $_audioFileName');
if (_recorderSubscription != null) {
_recorderSubscription.cancel();
_recorderSubscription = null;
}
this.setState(() {
this._isRecording = false;
final RegExp regexp = RegExp(
'(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}');
final guid = regexp.stringMatch(result);
this._recordedFilePath =
'/var/mobile/Containers/Data/Application/$guid/tmp/$_audioFileName';
});
} catch (err) {
print('stopRecorder error: $err');
}
}
void startPlayer() async {
final path = await flutterSound.startPlayer(_audioFileName);
await flutterSound.setVolume(1.0);
print('startPlayer: $_audioFileName');
try {
_playerSubscription = flutterSound.onPlayerStateChanged.listen((e) {
if (e != null) {
DateTime date = new DateTime.fromMillisecondsSinceEpoch(
e.currentPosition.toInt());
String txt = DateFormat('mm:ss:SS', 'en_US').format(date);
this.setState(() {
this._isPlaying = true;
this._playerTxt = txt.substring(0, 8);
});
}
});
} catch (err) {
print('error: $err');
}
}
void stopPlayer() async {
try {
String result = await flutterSound.stopPlayer();
print('stopPlayer: $result');
if (_playerSubscription != null) {
_playerSubscription.cancel();
_playerSubscription = null;
}
this.setState(() {
this._isPlaying = false;
});
} catch (err) {
print('error: $err');
}
}
void pausePlayer() async {
String result = await flutterSound.pausePlayer();
print('pausePlayer: $result');
}
void resumePlayer() async {
String result = await flutterSound.resumePlayer();
print('resumePlayer: $result');
}
void seekToPlayer(int milliSecs) async {
int secs = Platform.isIOS ? milliSecs / 1000 : milliSecs;
String result = await flutterSound.seekToPlayer(secs);
print('seekToPlayer: $result');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Запись аудио')),
body: ListView(
children: <Widget>[
// recorded timer
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 24.0, bottom: 16.0),
child: Text(
this._recorderTxt,
style: TextStyle(
fontSize: 48.0,
color: Colors.black,
),
),
),
],
),
// record or stop
Row(
children: <Widget>[
Container(
width: 56.0,
height: 56.0,
child: ClipOval(
child: FlatButton(
onPressed: () {
if (!this._isRecording) {
return this.startRecorder();
}
this.stopRecorder();
},
padding: EdgeInsets.all(8.0),
child: Icon(
this._isRecording ? Icons.stop : Icons.mic,
size: 50.0,
)),
),
),
],
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
),
// playing timer
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 60.0, bottom: 16.0),
child: Text(
this._playerTxt,
style: TextStyle(
fontSize: 48.0,
color: Colors.black,
),
),
),
],
),
// play pause or stop
Row(
children: <Widget>[
Container(
width: 56.0,
height: 56.0,
child: ClipOval(
child: FlatButton(
onPressed: () {
startPlayer();
},
padding: EdgeInsets.all(8.0),
child: Icon(Icons.play_arrow),
),
),
),
Container(
width: 56.0,
height: 56.0,
child: ClipOval(
child: FlatButton(
onPressed: () {
pausePlayer();
},
padding: EdgeInsets.all(8.0),
child: Icon(
Icons.pause,
size: 36.0,
),
),
),
),
Container(
width: 56.0,
height: 56.0,
child: ClipOval(
child: FlatButton(
onPressed: () {
stopPlayer();
},
padding: EdgeInsets.all(8.0),
child: Icon(
Icons.stop,
size: 28.0,
),
),
),
),
],
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
),
InkWell(
onTap: _recordedFilePath == null
? null
: () async {
final file = File(_recordedFilePath);
// final len = await file.length();
Navigator.pop(context, file);
},
child: Icon(
Icons.save,
size: 50.0,
color:
_recordedFilePath == null ? Colors.grey : Colors.blueAccent,
))
],
),
);
}
}
The idea would be you could build an app that allows you to monitor that microphone pickup via headphones, before and while recording audio, similar to what field recorders allow you to do with monitoring.
If you think it is possible let me know if you have any ideas where to start digging into the native code and I could attempt a PR.
Hi, when player ends playing audio file it stops automatically, but i can't set callback on this behavior.
fs.onPlayerStateChanged
returns only current position, and doesn't return any if audio file is ended.
Thanks, Eugene
in iOS Platform
_TypeError (type 'int' is not a subtype of type 'String')
1.3.1
[✓] Flutter (Channel stable, v1.0.0, on Mac OS X 10.14 18A391, locale en-MY)
[✓] Android toolchain - develop for Android devices (Android SDK 28.0.3)
[✓] iOS toolchain - develop for iOS devices (Xcode 10.1)
[✓] Android Studio (version 3.2)
[✓] VS Code (version 1.31.0)
[✓] Connected device (1 available)
IOS
play according to the selected audio
When screen has multiple recorded audio, the audio doesn't play correctly.
Real Device
import` 'package:flutter/material.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'dart:async';
import 'package:intl/intl.dart' show DateFormat;
class AudioScreen extends StatefulWidget {
@override
State createState() => new AudioScreenState();
}
class AudioScreenState extends State<AudioScreen> {
bool _isRecording = false;
bool openOption = false;
final TextEditingController _chatController = new TextEditingController();
final List<AudioPlayer> _messages = <AudioPlayer>[];
var initMicOffset = { 'x': 0.0, 'y': 0.0 };
Timer timerMic = null;
bool _visibleMic = true;
String _recordTimer;
StreamSubscription _recorderSubscription;
FlutterSound flutterSound = new FlutterSound();
bool micCancelling = false;
String micCancellingMsg = "Release to cancel.";
bool _onFocusInput = false;
final inputFocus = FocusNode();
String voiceRecordDir;
var slideToCancelOffset = 0.0;
var _visibleSlideToCancel = 1.0;
@override
void initState() {
// use local recorded audio
AudioPlayer message = AudioPlayer(
fileURL: '/var/mobile/Containers/Data/Application/A89DF404-F7E5-455E-B587-6436A83EEA14/Documents/1549974570624.m4a'
);
_messages.insert(0, message);
message = AudioPlayer(
fileURL: '///var/mobile/Containers/Data/Application/A89DF404-F7E5-455E-B587-6436A83EEA14/Documents/1549974575341.m4a'
);
_messages.insert(0, message);
super.initState();
}
@override
Widget build(BuildContext context) {
return SafeArea(
top: false,
bottom: true,
child: new Scaffold(
appBar: new AppBar(
title: new Text("Audio Player"),
),
body: new Column(
children: <Widget>[
Flexible(
child: ListView.builder(
padding: new EdgeInsets.all(8.0),
reverse: false,
itemBuilder: (_, int index) => _messages[index],
itemCount: _messages.length,
),
),
new Divider(
height: 1.0,
),
],
)
));
}
}
class AudioPlayer extends StatefulWidget {
final String fileURL;
AudioPlayer({
this.fileURL });
@override
AudioPlayerState createState() {
return new AudioPlayerState();
}
}
class AudioPlayerState extends State<AudioPlayer> {
String progressString;
String _playerTime;
bool _isPlaying = false;
final FlutterSound flutterSound = new FlutterSound();
StreamSubscription _playerSubscription;
double slider_current_position = 0.0;
double max_duration = 1.0;
bool isResume = false;
@override
void dispose() {
super.dispose();
stopPlayer(false);
}
void startPlayer() async{
print("the startPlayer is, file: ${widget.fileURL}, isResume: $isResume");
if(isResume){
resumePlayer();
}else{
isResume = true;
String result = await flutterSound.startPlayer(widget.fileURL);
await flutterSound.setVolume(1.0);
try {
this._isPlaying = true;
_playerSubscription = flutterSound.onPlayerStateChanged.listen((e) {
if (e != null) {
slider_current_position = e.currentPosition;
max_duration = e.duration;
DateTime date = new DateTime.fromMillisecondsSinceEpoch(e.duration.toInt() - e.currentPosition.toInt());
String txt = DateFormat('mm:ss:SS', 'en_US').format(date);
if(mounted) {
this.setState(() {
this._playerTime = txt.substring(0, 8);
});
}
}
else{
slider_current_position = 0.0;
isResume = false;
this.setState(() {
this._isPlaying = false;
});
}
});
} catch (err) {
print('error: $err');
}
}
}
void stopPlayer(state) async{
try {
isResume = false;
if(this._isPlaying){
String result = await flutterSound.stopPlayer();
print('stopPlayer: $result');
if (_playerSubscription != null) {
_playerSubscription.cancel();
_playerSubscription = null;
}
if(state){
this.setState(() {
this.slider_current_position = 0.0;
this._isPlaying = false;
});
}
}
} catch (err) {
print('error: $err');
}
}
void pausePlayer() async{
setState(() {
_isPlaying = false;
});
await flutterSound.pausePlayer();
}
void resumePlayer() async{
setState(() {
_isPlaying = true;
});
await flutterSound.resumePlayer();
}
Widget _audio(context){
return Container(
padding: const EdgeInsets.all(10.0),
decoration: new BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Colors.white,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: 50.0,
height: 40.0,
child: ClipOval(
child:
_isPlaying ?
FlatButton(
onPressed: () {
pausePlayer();
},
padding: EdgeInsets.all(5.0),
child: Icon(Icons.pause_circle_filled)
)
: FlatButton(
onPressed: () {
startPlayer();
},
padding: EdgeInsets.all(5.0),
child: Icon(Icons.play_circle_filled)
)
),
),
Container(
height: 40.0,
child: Slider(
value: slider_current_position,
min: 0.0,
max: max_duration,
divisions: max_duration.toInt()
)
)
],
)
);
}
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.symmetric(vertical: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
_audio(context),
],
)
);
}
}
can I return PCM data during recording?
1.3.3
$ flutter doctor -v
[✓] Flutter (Channel dev, v1.3.2, on Mac OS X 10.14.3 18D109, locale en-US)
• Flutter version 1.3.2 at /Users/ened/dev/flutter
• Framework revision 046f960ae2 (3 days ago), 2019-02-28 23:05:45 -0800
• Engine revision 99f3f7a9c2
• Dart version 2.2.1 (build 2.2.1-dev.0.0 7c70ab1817)
[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
• Android SDK at /usr/local/opt/android-sdk
• Android NDK location not configured (optional; useful for native profiling support)
• Platform android-28, build-tools 28.0.3
• ANDROID_HOME = /usr/local/opt/android-sdk
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1248-b01)
• All Android licenses accepted.
[!] iOS toolchain - develop for iOS devices (Xcode 10.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 10.1, Build version 10B61
✗ Verify that all connected devices have been paired with this computer in Xcode.
If all devices have been paired, libimobiledevice and ideviceinstaller may require updating.
To update with Brew, run:
brew update
brew uninstall --ignore-dependencies libimobiledevice
brew uninstall --ignore-dependencies usbmuxd
brew install --HEAD usbmuxd
brew unlink usbmuxd
brew link usbmuxd
brew install --HEAD libimobiledevice
brew install ideviceinstaller
• ios-deploy 1.9.4
• CocoaPods version 1.6.1
[✓] Android Studio (version 3.3)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin version 33.3.1
• Dart plugin version 182.5215
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1248-b01)
[✓] VS Code (version 1.31.1)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 2.24.0
[✓] Connected device (1 available)
• Pixel 2 • HT83G1A03545 • android-arm64 • Android 9 (API 28)
Android
Recording should start/stop smoothly and discard any recordings which are not used.
The plugin should handle such stress testing gracefully & make sure Android APIs are opened/closed on time.
Quickly starting & stopping will cause the stack trace below.
Pixel XL 2
Quickly start & stop the audio recording will yield a error like this:
E/FlutterSoundPlugin(19490): Exception:
E/FlutterSoundPlugin(19490): java.lang.IllegalStateException
E/FlutterSoundPlugin(19490): at android.media.MediaRecorder._setOutputFile(Native Method)
E/FlutterSoundPlugin(19490): at android.media.MediaRecorder.prepare(MediaRecorder.java:961)
E/FlutterSoundPlugin(19490): at com.dooboolab.fluttersound.FlutterSoundPlugin.startRecorder(FlutterSoundPlugin.java:155)
E/FlutterSoundPlugin(19490): at com.dooboolab.fluttersound.FlutterSoundPlugin.onMethodCall(FlutterSoundPlugin.java:66)
E/FlutterSoundPlugin(19490): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:201)
E/FlutterSoundPlugin(19490): at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:88)
E/FlutterSoundPlugin(19490): at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:202)
E/FlutterSoundPlugin(19490): at android.os.MessageQueue.nativePollOnce(Native Method)
E/FlutterSoundPlugin(19490): at android.os.MessageQueue.next(MessageQueue.java:326)
E/FlutterSoundPlugin(19490): at android.os.Looper.loop(Looper.java:160)
E/FlutterSoundPlugin(19490): at android.app.ActivityThread.main(ActivityThread.java:6718)
E/FlutterSoundPlugin(19490): at java.lang.reflect.Method.invoke(Native Method)
E/FlutterSoundPlugin(19490): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
E/FlutterSoundPlugin(19490): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Once this happens, the App needs to be restarted as the Plugin is not released/recreating a faulty MediaRecorder instance (perhaps another bug).
My suggestion is to introduce a single threaded command scheduler inside the plugin, which runs everything in a sequence.
For example:
Schedulers.from(Executors.newSingleThreadExecutor())
Then, this scheduler can be fed Runnable
s which run the actual plugin code.
flutter_sound: ^1.3.5
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel beta, v1.2.1, on Microsoft Windows [Version 10.0.17134.471], locale zh-CN)
[!] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
! Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses
[√] Android Studio (version 3.2)
[!] Android Studio (version 3.2)
X Flutter plugin not installed; this adds Flutter specific functionality.
X Dart plugin not installed; this adds Dart specific functionality.
[√] IntelliJ IDEA Ultimate Edition (version 2018.3)
[√] VS Code (version 1.31.1)
[√] Connected device (1 available)
Android
D/FlutterSoundPlugin(20851): startRecorder
D/AudioRecordPermission(20851): AudioRecordPermission
I/AudioRecordPermission(20851): remindWithResult:false
E/MediaRecorder(20851): output file has already been set
E/FlutterSoundPlugin(20851): Exception:
E/FlutterSoundPlugin(20851): java.lang.IllegalStateException
E/FlutterSoundPlugin(20851): at android.media.MediaRecorder._setOutputFile(Native Method)
E/FlutterSoundPlugin(20851): at android.media.MediaRecorder.setInterOutputFile(MediaRecorder.java:1006)
E/FlutterSoundPlugin(20851): at android.hsm.HwMediaPermWrapper.setOutputFile(HwMediaPermWrapper.java:139)
E/FlutterSoundPlugin(20851): at android.media.MediaRecorder.prepare(MediaRecorder.java:1026)
E/FlutterSoundPlugin(20851): at com.dooboolab.fluttersound.FlutterSoundPlugin.startRecorder(FlutterSoundPlugin.java:162)
E/FlutterSoundPlugin(20851): at com.dooboolab.fluttersound.FlutterSoundPlugin.onMethodCall(FlutterSoundPlugin.java:67)
E/FlutterSoundPlugin(20851): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:201)
E/FlutterSoundPlugin(20851): at io.flutter.view.FlutterNativeView$PlatformMessageHandlerImpl.handleMessageFromDart(FlutterNativeView.java:188)
E/FlutterSoundPlugin(20851): at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:202)
E/FlutterSoundPlugin(20851): at android.os.MessageQueue.nativePollOnce(Native Method)
E/FlutterSoundPlugin(20851): at android.os.MessageQueue.next(MessageQueue.java:386)
E/FlutterSoundPlugin(20851): at android.os.Looper.loop(Looper.java:169)
E/FlutterSoundPlugin(20851): at android.app.ActivityThread.main(ActivityThread.java:7470)
E/FlutterSoundPlugin(20851): at java.lang.reflect.Method.invoke(Native Method)
E/FlutterSoundPlugin(20851): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
E/FlutterSoundPlugin(20851): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:958)
I/flutter (20851): stopRecorder error: Exception: Recorder already stopped.
Real Device
void startRecorder() async {
try {
this.path = await flutterSound.startRecorder(null, sampleRate: 16000, numChannels: 1, bitRate: 16);
_recorderSubscription =
flutterSound.onRecorderStateChanged.listen((e) {});
_dbPeakSubscription =
flutterSound.onRecorderDbPeakChanged.listen((value) {
print("got update -> $value");
});
setState(() => this._isRecording = true);
} catch (err) {
print('startRecorder error: $err');
setState(() => this._isRecording = false);
}
}
In ios 12.0.1, in the example, the first recorded resource is always played.
(Besides the first play is normal, other play is noise)
as I understand, ios and android starting with api26 support pausing recording.
on android before api26 you can still manually merge pieces together.
as for playback speed, it's just a nice thing to have.
also I'm quite curious about the background play, as far as i know, at least on android, most app uses notification area as a music control panel to keep the app alive when in background. do we have something like this built-in or we need to use some first/third party plugin for this?
thanks
An existing application working in 1.2.1 of the plugin was recently updated to 1.2.2 - now when we run our app, and start to record sound - our ticker display stays at 00:00:00. The onRecorderStateChanged event is fired constantly - but RecordStatus->currentPosition is always 0.0
1.2.2
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.0.0, on Mac OS X 10.14.2 18C54, locale en-GB)
[✓] Android toolchain - develop for Android devices (Android SDK 28.0.3)
[✓] iOS toolchain - develop for iOS devices (Xcode 10.1)
[✓] Android Studio (version 3.1)
[✓] IntelliJ IDEA Community Edition (version 2018.2.3)
[✓] VS Code (version 1.30.2)
[✓] Connected device (2 available)
iOS
Expect currentPosition of RecordStatus to tick over at each new event.
currentPosition is always 0.0
iOS 10.x and above - all simulators.
Just run the sample app that ships with this plugin - hit record. You will see in iOS no ticker gets displayed and the display stays at 00:00
File created by the library is not available in ios:
String path = await flutterSound.startRecorder(null); _file = io.File(path);
path in mobil file:///private/var/mobile/Containers/Data/Application/2272A03E-2497-416C-98EC-69109A431A8B/tmp/sound.m4a
If you need to specify permissions in ios or what path to add?
1.2.1
At the moment, startPlayer requires a URI, which the assets don't have. I think I can hack a workaround to this via path_provider, but it would be useful to be able to playback directly from assets as well.
Thanks for the library!
bool _isRecording = false;
bool _isPlaying = false;
to public method get for view the state the flutter_sound?
THANKSSSS
1.2.4
[√] Flutter (Channel stable, v1.0.0, on Microsoft Windows [Version 10.0.17134.523], locale en-US)
[!] Android toolchain - develop for Android devices (Android SDK 28.0.3)
X Android license status unknown.
[√] Android Studio (version 3.0)
[√] VS Code, 64-bit edition (version 1.30.2)
[√] Connected device (1 available)
Android
to seek to the correct position
seeks to the current position + the new value. I know why it is doing it. In the android code, the seek method takes in an int millis and it adds that value to the current millis that is playing, which it shouldn't. Just comment it out and it works.
Real device
Use a Slider widget and in the onChanged property to set the media player to seek to the new 'dragged' value
flutter_sound: ^1.3.2
I can't get the play state because the play state variable is private.So I don't know if the play is done.When I call stopPlayer() again, an inevitable error occurs.I don't know how to solve it.
hi sir, I am happy to design the logo for this project. because you have offered me this project in the react-native-audio-recorder-player issues project. thanks sir. I will design it.
1.- add flutter_sound: ^1.3.5
2.- debug
Error:
=== BUILD TARGET Pods-Runner OF PROJECT Pods WITH CONFIGURATION Debug === ld: warning: linking against a dylib which is not safe for use in application extensions: /Users/zimbronapps/flutter/bin/cache/artifacts/engine/ios/Flutter.framework/Flutter duplicate symbol __channel in: /Users/zimbronapps/Projects/Flutter/loteria/build/ios/Debug-iphonesimulator/firebase_admob/libfirebase_admob.a(FLTMobileAd.o) /Users/zimbronapps/Projects/Flutter/loteria/build/ios/Debug-iphonesimulator/flutter_sound/libflutter_sound.a(FlutterSoundPlugin.o) ld: 1 duplicate symbol for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) Could not build the application for the simulator. Error launching application on iPhone 7 Plus.
1.2.4
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.0.0, on Mac OS X 10.14.1 18B75, locale en-CA)
[✓] Android toolchain - develop for Android devices (Android SDK 28.0.3)
[✓] iOS toolchain - develop for iOS devices (Xcode 10.1)
[✓] Android Studio (version 3.2)
[✓] Connected device (1 available)
• No issues found!
This Error accurs on Android.
Expected behavior is it would start recording audio
Error Shows with this:
E/MethodChannel#flutter_sound(13084): Failed to handle method call
E/MethodChannel#flutter_sound(13084): java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer
E/MethodChannel#flutter_sound(13084): at com.dooboolab.fluttersound.FlutterSoundPlugin.onMethodCall(FlutterSoundPlugin.java:62)
E/MethodChannel#flutter_sound(13084): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:200)
E/MethodChannel#flutter_sound(13084): at io.flutter.view.FlutterNativeView.handlePlatformMessage(FlutterNativeView.java:163)
E/MethodChannel#flutter_sound(13084): at android.os.MessageQueue.nativePollOnce(Native Method)
E/MethodChannel#flutter_sound(13084): at android.os.MessageQueue.next(MessageQueue.java:326)
E/MethodChannel#flutter_sound(13084): at android.os.Looper.loop(Looper.java:160)
E/MethodChannel#flutter_sound(13084): at android.app.ActivityThread.main(ActivityThread.java:6669)
E/MethodChannel#flutter_sound(13084): at java.lang.reflect.Method.invoke(Native Method)
E/MethodChannel#flutter_sound(13084): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
E/MethodChannel#flutter_sound(13084): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
E/flutter (13084): [ERROR:flutter/shell/common/shell.cc(184)] Dart Error: Unhandled exception:
E/flutter (13084): Exception: PlatformException(error, java.lang.Double cannot be cast to java.lang.Integer, null)
E/flutter (13084): #0 FlutterSound.startRecorder (package:flutter_sound/flutter_sound.dart:102:7)
E/flutter (13084):
E/flutter (13084): #1 _RecordingPageState._onRecordPressed (package:speechdb/ui/recording_page.dart:217:35)
E/flutter (13084):
E/flutter (13084): #2 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:507:14)
E/flutter (13084): #3 _InkResponseState.build. (package:flutter/src/material/ink_well.dart:562:30)
E/flutter (13084): #4 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:102:24)
E/flutter (13084): #5 TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:242:9)
E/flutter (13084): #6 TapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:175:7)
E/flutter (13084): #7 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:315:9)
E/flutter (13084): #8 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:73:12)
E/flutter (13084): #9 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:101:11)
E/flutter (13084): #10 _WidgetsFlutterBinding&BindingBase&GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:180:19)
E/flutter (13084): #11 _WidgetsFlutterBinding&BindingBase&GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:158:22)
E/flutter (13084): #12 _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:138:7)
E/flutter (13084): #13 _WidgetsFlutterBinding&BindingBase&GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:101:7)
E/flutter (13084): #14 _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:85:7)
E/flutter (13084): #15 _invoke1 (dart:ui/hooks.dart:168:13)
E/flutter (13084): #16 _dispatchPointerDataPacket (dart:ui/hooks.dart:122:5)
Emulator and Real Device
When I call: path = await flutterSound.startRecorder(filename);
mp4后端无法直接播放
v1.0.6
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel unknown, v1.3.2, on Microsoft Windows [Version 10.0.17134.590], locale en-AT)
[√] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
[√] Android Studio (version 3.3)
[√] Connected device (1 available)
• No issues found!
Android - Samsung S8 - Android 9 Pie
Can play remote files..
Cannot play remote files.
Real device.
Try to play any file from remote URL.
I/MediaPlayer(26707): Need to enable context aware info
V/MediaPlayer-JNI(26707): native_setup
I/flutter (26707): error: Exception: Player already stopped.
V/MediaPlayerNative(26707): constructor
V/MediaPlayerNative(26707): setListener
V/MediaHTTPService(26707): MediaHTTPService(android.media.MediaHTTPService@b2558b2): Cookies: null
V/MediaPlayerNative(26707): setVideoSurfaceTexture
V/MediaPlayerNative(26707): prepare
V/MediaHTTPService(26707): makeHTTPConnection: CookieManager created: java.net.CookieManager@b993003
V/MediaHTTPService(26707): makeHTTPConnection(android.media.MediaHTTPService@b2558b2): cookieHandler: java.net.CookieManager@b993003 Cookies: null
D/MediaHTTPConnection(26707): setReadTimeOut = 15000ms
D/NetworkSecurityConfig(26707): Using Network Security Config from resource network_security_config debugBuild: true
D/MediaHTTPConnection(26707): setReadTimeout with 15000ms
I/System.out(26707): (HTTPLog)-Static: isSBSettingEnabled false
D/MediaHTTPConnection(26707): setReadTimeout with 15000ms
I/System.out(26707): (HTTPLog)-Static: isSBSettingEnabled false
D/MediaHTTPConnection(26707): setReadTimeout with 15000ms
I/System.out(26707): (HTTPLog)-Static: isSBSettingEnabled false
D/MediaHTTPConnection(26707): setReadTimeout with 15000ms
I/System.out(26707): (HTTPLog)-Static: isSBSettingEnabled false
D/MediaHTTPConnection(26707): setReadTimeout with 15000ms
I/System.out(26707): (HTTPLog)-Static: isSBSettingEnabled false
D/MediaHTTPConnection(26707): setReadTimeout with 15000ms
I/System.out(26707): (HTTPLog)-Static: isSBSettingEnabled false
D/MediaHTTPConnection(26707): setReadTimeout with 15000ms
I/System.out(26707): (HTTPLog)-Static: isSBSettingEnabled false
D/MediaHTTPConnection(26707): setReadTimeout with 15000ms
I/System.out(26707): (HTTPLog)-Static: isSBSettingEnabled false
D/MediaHTTPConnection(26707): setReadTimeout with 15000ms
I/System.out(26707): (HTTPLog)-Static: isSBSettingEnabled false
D/MediaHTTPConnection(26707): setReadTimeout with 15000ms
I/System.out(26707): (HTTPLog)-Static: isSBSettingEnabled false
D/MediaHTTPConnection(26707): setReadTimeout with 15000ms
I/System.out(26707): (HTTPLog)-Static: isSBSettingEnabled false
D/MediaHTTPConnection(26707): setReadTimeout with 15000ms
I/System.out(26707): (HTTPLog)-Static: isSBSettingEnabled false
D/MediaHTTPConnection(26707): setReadTimeout with 15000ms
I/System.out(26707): (HTTPLog)-Static: isSBSettingEnabled false
D/MediaHTTPConnection(26707): setReadTimeout with 15000ms
I/System.out(26707): (HTTPLog)-Static: isSBSettingEnabled false
V/MediaPlayerNative(26707): message received msg=300, ext1=0, ext2=0
V/MediaPlayerNative(26707): Received SEC_MM_PLAYER_CONTEXT_AWARE
V/MediaPlayerNative(26707): callback application
V/MediaPlayerNative(26707): back from callback
V/MediaPlayerNative(26707): message received msg=100, ext1=1, ext2=-2147483648
E/MediaPlayerNative(26707): error (1, -2147483648)
V/MediaPlayerNative(26707): signal application thread
V/MediaPlayerNative(26707): prepare complete - status=1
E/FlutterSoundPlugin(26707): startPlayer() exception
E/flutter (26707): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: Exception: PlatformException(ERR_UNKNOWN, ERR_UNKNOWN, Prepare failed.: status=0x1)
E/flutter (26707): #0 FlutterSound.startPlayer (package:flutter_sound/flutter_sound.dart:163:7)
E/flutter (26707):
It worked fine on S8 with Android 8. Also it works now on other device with Android 8 without any problem.
please add setSpeed:
thanks for your works!!
i love!
Android:
case "setSpeed":
double speed = call.argument("speed");
this.setSpeed(speed, result);
break;
@OverRide
public void setSpeed(double speed, final Result result) {
if (this.model.getMediaPlayer() == null) {
// result.error(ERR_PLAYER_IS_NULL, ERR_PLAYER_IS_NULL, ERR_PLAYER_IS_NULL);
return;
}
if (this.model.getMediaPlayer().isPlaying()==false) {
// result.error(ERR_PLAYER_IS_NULL, ERR_PLAYER_IS_NULL, ERR_PLAYER_IS_NULL);
return;
}
if (android.os.Build.VERSION.SDK_INT < 23) {
Log.w("RNSoundModule", "setSpeed ignored due to sdk limit");
return;
}
float mSpeed = (float) speed;
this.model.getMediaPlayer().setPlaybackParams( this.model.getMediaPlayer().getPlaybackParams().setSpeed(mSpeed));
result.success("Set speed");
ios
} else if ([@"setSpeed" isEqualToString:call.method]) {
NSNumber* speed = (NSNumber*)call.arguments[@"speed"];
[self setSpeed:[speed doubleValue] result:result];
} else {
(void)setSpeed:(double) speed result: (FlutterResult)result {
/*
if (!self->audioPlayer) {
NSLog(@"Desde IOS setSpeed SELFT es: @%.2f", speed);
// self->audioPlayer = [[AVAudioPlayer alloc] initWithData:data error:nil];
self->audioPlayer.rate=speed;
result(@"speed set");
}else{
NSLog(@"Desde IOS setSpeed NO SELFT es: @%.2f", speed);
audioPlayer.rate=speed;
result(@"speed set");
}
*/
if (audioPlayer) {
// [audioPlayer rate: speed];
// audioPlayer.enableRate=true;
NSLog(@"Desde IOS setSpeed es: @%.2f", speed);
audioPlayer.rate=speed;
result(@"speed set");
} else {
result([FlutterError
errorWithCode:@"Audio Player"
message:@"5.player is not set"
details:nil]);
}
1.2.4
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.0.0, on Mac OS X 10.14.1 18B75, locale en-CA)
[✓] Android toolchain - develop for Android devices (Android SDK 28.0.3)
[✓] iOS toolchain - develop for iOS devices (Xcode 10.1)
[✓] Android Studio (version 3.2)
[✓] Connected device (1 available)
• No issues found!
Android
Record audio and save to the file.
When startRecorder
is called with or without a fileName, the audio is not saved on the file.
That is the file size is always 8.65KB.
Emulator
Testing in both iOS and Android on emulators and real devices - the file size produced with this plugin is very high. As an example 17 seconds recording gives a file size of 4.3Mb. The plugin audio_recorder gives the same 17 second recording as 59.2k which is a considerable difference - thus , in its current form , this renders the plugin unusable as even if we were to compress recordings and uncompress there is a noticeable lag in application performance when compressing/uncompressing. Is it possible to produce AAC files which are considerably smaller in size or allow a switch to select output format ? If so - this would make this an invaluable plugin.
1.1.5
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel dev, v0.10.2, on Mac OS X 10.14 18A391, locale en-RO)
[✓] Android toolchain - develop for Android devices (Android SDK 28.0.3)
[✓] iOS toolchain - develop for iOS devices (Xcode 10.1)
[✓] Android Studio (version 3.2)
[✓] IntelliJ IDEA Ultimate Edition (version 2018.2.5)
[✓] VS Code (version 1.28.2)
[✓] Connected device (1 available)
• No issues found!
seekToPlayer throws exception on Android (because the Dart code sends the 'seekToPlayer' method name while the Android code listens for 'seekPlayer'. Problem only occurs on Android.
duplicate symbol __channel in flutter_sound plugin and audioplayer plugin
1.3.3
IOS is ok but Android make mistakes when start play remote voice
_playerSubscription = _flutterSound.onPlayerStateChanged.listen((e) {
});
e.currentPosition And e.duration is always 0
Real Device
1.2.1
flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel dev, v0.11.13, on Mac OS X 10.14.2 18C54, locale en-FI)
[✓] Android toolchain - develop for Android devices (Android SDK 27.0.3)
[!] iOS toolchain - develop for iOS devices (Xcode 10.1)
✗ Verify that all connected devices have been paired with this computer in Xcode.
If all devices have been paired, libimobiledevice and ideviceinstaller may require updating.
To update with Brew, run:
brew update
brew uninstall --ignore-dependencies libimobiledevice
brew uninstall --ignore-dependencies usbmuxd
brew install --HEAD usbmuxd
brew unlink usbmuxd
brew link usbmuxd
brew install --HEAD libimobiledevice
brew install ideviceinstaller
✗ ios-deploy out of date (1.9.4 is required). To upgrade with Brew:
brew upgrade ios-deploy
[!] Android Studio (not installed)
[!] VS Code (version 1.30.1)
[✓] Connected device (1 available)
Android
player should not crash
player crashes, which crashes the whole app
real device, Samsung Galaxy S9
let the audio play until end, it does not happen cosistently
V/MediaPlayer-JNI( 1705): stop
V/MediaPlayerNative( 1705): stop
V/MediaPlayerNative( 1705): message received msg=8, ext1=0, ext2=0
V/MediaPlayerNative( 1705): unrecognized message: (8, 0, 0)
V/MediaPlayerNative( 1705): callback application
V/MediaPlayerNative( 1705): back from callback
V/MediaPlayer( 1705): resetDrmState: mDrmInfo=null mDrmProvisioningThread=null mPrepareDrmInProgress=false mActiveDrmScheme=false
V/MediaPlayer( 1705): cleanDrmObj: mDrmObj=null mDrmSessionId=null
V/MediaPlayer-JNI( 1705): release
V/MediaPlayerNative( 1705): setListener
V/MediaPlayerNative( 1705): disconnect
V/MediaPlayer-JNI( 1705): getDuration: 2400 (msec)
E/AndroidRuntime( 1705): FATAL EXCEPTION: Timer-2
E/AndroidRuntime( 1705): Process: com.lacorder.lacorder, PID: 1705
E/AndroidRuntime( 1705): java.lang.IllegalStateException
E/AndroidRuntime( 1705): at android.media.MediaPlayer.getCurrentPosition(Native Method)
E/AndroidRuntime( 1705): at com.dooboolab.fluttersound.FlutterSoundPlugin$2$1.run(FlutterSoundPlugin.java:232)
E/AndroidRuntime( 1705): at java.util.TimerThread.mainLoop(Timer.java:555)
E/AndroidRuntime( 1705): at java.util.TimerThread.run(Timer.java:505)
V/MediaPlayerNative( 1705): destructor
V/MediaPlayerNative( 1705): disconnect
W/MediaPlayer( 1705): mediaplayer went away with unhandled events
Listening to player state through onPlayerStateChanged
provides a PlayState
which contains duration
and currentPosition
, but none of those concern the actual state. There should be a field that indicates at least whether the player is paused, stopped or playing.
both
Reverse audio after recording.
Not reversing.
Is there a way to reverse audio file on play or record step?
1.3.1
Android (not tried on iOS)
Clear Recorded Sound
Only Noises are present
Real device - Nokia 8.1
minute is always 30.
hello i am getting a file not found error when setting the uri on startRecorder
can you give example on how to properly load custom uri/path?
does the file need to exist or it will be created?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.