运行 nativescript/javascript 中的非阻塞、高性能 activity
Running a non-blocking, high-performance activity in nativescript/javascript
这个问题是关于 运行在 nativescript 中使用一个非阻塞的、高性能的 activity,它需要通过直接访问从麦克风读取和保存原始音频的简单任务。通过本机硬件 Android API。我相信我已经把nativescript框架发挥到极致了,我需要专家的帮助。
我正在使用 Nativescript Android 构建一个 WAV 录音机。 here(下面的相关代码)描述了本机实现。
简而言之,这可以通过从 android.media.AudioRecord 缓冲区读取音频流,然后在单独的线程中将缓冲区写入文件来完成,如下所述:
本机 Android 实现
startRecording()
由按下按钮触发,并启动一个新线程 运行s writeAudioDataToFile()
:
private void startRecording() {
// ... init Recorder
recorder.startRecording();
isRecording = true;
recordingThread = new Thread(new Runnable() {
@Override
public void run() {
writeAudioDataToFile();
}
}, "AudioRecorder Thread");
recordingThread.start();
}
通过将 isRecording
设置为 false
停止录制(stopRecording()
由按下按钮触发):
private void stopRecording() {
isRecording = false;
recorder.stop();
recorder.release();
recordingThread = null;
}
如果 isRecording = false,则停止读取和保存缓冲区:
private void writeAudioDataToFile() {
// ... init file and buffer
ByteArrayOutputStream recData = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(recData);
int read = 0;
while(isRecording) {
read = recorder.read(data, 0, bufferSize);
for(int i = 0; i < bufferReadResult; i++) {
dos.writeShort(buffer[i]);
}
}
}
我的 Nativescript javascript 实现:
我写了一个 nativescript 打字稿代码,它的功能与上面的 Android 代码相同。我遇到的问题 #1 是我不能 运行 while(isRecording)
因为 javascript 线程会在 while
循环内忙 运行ning,并且会永远无法捕捉到 运行 stopRecording()
.
的按钮点击
我尝试通过使用 setInterval
进行异步执行来解决问题 #1,如下所示:
startRecording()
由按钮按下触发,并设置执行 writeAudioDataToFile()
:
的时间间隔为 10ms
startRecording() {
this.audioRecord.startRecording();
this.audioBufferSavingTimer = setInterval(() => this.writeAudioDataToFile(), 10);
}
writeAudioDataToFile()
回调每 10 毫秒排队一次:
writeAudioDataToFile() {
let bufferReadResult = this.audioRecord.read(
this.buffer,
0,
this.minBufferSize / 4
);
for (let i = 0; i < bufferReadResult; i++) {
dos.writeShort(buffer[i]);
}
}
通过清除时间间隔停止录制(stopRecording()
由按下按钮触发):
stopRecording() {
clearInterval(this.audioBufferSavingTimer);
this.audioRecord.stop();
this.audioRecord.release();
}
问题 #2:虽然这很有效,但在许多情况下它会使 UI 冻结 1-10 秒(例如在单击按钮停止录制后)。
我试图将执行 writeAudioDataToFile()
的时间间隔从 10 毫秒更改为 0 毫秒,最多 1000 毫秒(同时具有非常大的缓冲区),但是 UI 冻结时间更长,并且我遇到了保存数据丢失(未保存到文件的缓冲数据)。
我尝试使用 nativescript 工作线程将此操作卸载到单独的线程,如 here 所述,其中 startRecording()
和 stopRecording()
由发送到线程的消息调用,例如这个:
global.onmessage = function(msg) {
if (msg.data === 'startRecording') {
startRecording();
} else if (msg.data === 'stopRecording') {
stopRecording();
}
}
这解决了 UI 问题,但产生了问题 #3:记录器 stop 没有按时执行(即在 stop 后记录停止 10 到 50 秒=86=] msg.data 被工作线程接收)。我尝试在工作线程内的 setInterval
中使用不同的时间间隔(0 毫秒到 1000 毫秒),但这并没有解决问题,甚至使 stopRecording()
的执行延迟更大。
有没有人知道如何在 nativescript/javascript 中执行这种非阻塞高性能记录 activity?
有没有更好的方法来解决我上面描述的问题 #1(javascript 异步执行)?
谢谢
我会在实际 Java 中保留完整的 Java 实现,您可以通过在插件文件夹中创建一个 java 文件来做到这一点:
platforms/android/java,所以可能是这样的:
platforms/android/java/org/nativescript/AudioRecord.java
在那里你可以做所有线程化的事情,所以你不会因为 UI 被阻塞而烦恼。您可以直接从 NativeScript 调用 Java 方法来开始和停止录制。当您构建项目时,Java 文件将自动编译并包含。
您可以通过从您的插件生成的 .aar 文件 ({plugin_name}.aar) 中抓取 classes.jar 来从您的 Java class 生成类型并生成它的类型声明:https://docs.nativescript.org/core-concepts/android-runtime/metadata/generating-typescript-declarations
这样您就可以在编辑器中获得所有 method/class/type 信息。
这个问题是关于 运行在 nativescript 中使用一个非阻塞的、高性能的 activity,它需要通过直接访问从麦克风读取和保存原始音频的简单任务。通过本机硬件 Android API。我相信我已经把nativescript框架发挥到极致了,我需要专家的帮助。
我正在使用 Nativescript Android 构建一个 WAV 录音机。 here(下面的相关代码)描述了本机实现。
简而言之,这可以通过从 android.media.AudioRecord 缓冲区读取音频流,然后在单独的线程中将缓冲区写入文件来完成,如下所述:
本机 Android 实现
startRecording()
由按下按钮触发,并启动一个新线程 运行s writeAudioDataToFile()
:
private void startRecording() {
// ... init Recorder
recorder.startRecording();
isRecording = true;
recordingThread = new Thread(new Runnable() {
@Override
public void run() {
writeAudioDataToFile();
}
}, "AudioRecorder Thread");
recordingThread.start();
}
通过将 isRecording
设置为 false
停止录制(stopRecording()
由按下按钮触发):
private void stopRecording() {
isRecording = false;
recorder.stop();
recorder.release();
recordingThread = null;
}
如果 isRecording = false,则停止读取和保存缓冲区:
private void writeAudioDataToFile() {
// ... init file and buffer
ByteArrayOutputStream recData = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(recData);
int read = 0;
while(isRecording) {
read = recorder.read(data, 0, bufferSize);
for(int i = 0; i < bufferReadResult; i++) {
dos.writeShort(buffer[i]);
}
}
}
我的 Nativescript javascript 实现:
我写了一个 nativescript 打字稿代码,它的功能与上面的 Android 代码相同。我遇到的问题 #1 是我不能 运行 while(isRecording)
因为 javascript 线程会在 while
循环内忙 运行ning,并且会永远无法捕捉到 运行 stopRecording()
.
我尝试通过使用 setInterval
进行异步执行来解决问题 #1,如下所示:
startRecording()
由按钮按下触发,并设置执行 writeAudioDataToFile()
:
startRecording() {
this.audioRecord.startRecording();
this.audioBufferSavingTimer = setInterval(() => this.writeAudioDataToFile(), 10);
}
writeAudioDataToFile()
回调每 10 毫秒排队一次:
writeAudioDataToFile() {
let bufferReadResult = this.audioRecord.read(
this.buffer,
0,
this.minBufferSize / 4
);
for (let i = 0; i < bufferReadResult; i++) {
dos.writeShort(buffer[i]);
}
}
通过清除时间间隔停止录制(stopRecording()
由按下按钮触发):
stopRecording() {
clearInterval(this.audioBufferSavingTimer);
this.audioRecord.stop();
this.audioRecord.release();
}
问题 #2:虽然这很有效,但在许多情况下它会使 UI 冻结 1-10 秒(例如在单击按钮停止录制后)。
我试图将执行 writeAudioDataToFile()
的时间间隔从 10 毫秒更改为 0 毫秒,最多 1000 毫秒(同时具有非常大的缓冲区),但是 UI 冻结时间更长,并且我遇到了保存数据丢失(未保存到文件的缓冲数据)。
我尝试使用 nativescript 工作线程将此操作卸载到单独的线程,如 here 所述,其中 startRecording()
和 stopRecording()
由发送到线程的消息调用,例如这个:
global.onmessage = function(msg) {
if (msg.data === 'startRecording') {
startRecording();
} else if (msg.data === 'stopRecording') {
stopRecording();
}
}
这解决了 UI 问题,但产生了问题 #3:记录器 stop 没有按时执行(即在 stop 后记录停止 10 到 50 秒=86=] msg.data 被工作线程接收)。我尝试在工作线程内的 setInterval
中使用不同的时间间隔(0 毫秒到 1000 毫秒),但这并没有解决问题,甚至使 stopRecording()
的执行延迟更大。
有没有人知道如何在 nativescript/javascript 中执行这种非阻塞高性能记录 activity? 有没有更好的方法来解决我上面描述的问题 #1(javascript 异步执行)?
谢谢
我会在实际 Java 中保留完整的 Java 实现,您可以通过在插件文件夹中创建一个 java 文件来做到这一点: platforms/android/java,所以可能是这样的: platforms/android/java/org/nativescript/AudioRecord.java
在那里你可以做所有线程化的事情,所以你不会因为 UI 被阻塞而烦恼。您可以直接从 NativeScript 调用 Java 方法来开始和停止录制。当您构建项目时,Java 文件将自动编译并包含。
您可以通过从您的插件生成的 .aar 文件 ({plugin_name}.aar) 中抓取 classes.jar 来从您的 Java class 生成类型并生成它的类型声明:https://docs.nativescript.org/core-concepts/android-runtime/metadata/generating-typescript-declarations
这样您就可以在编辑器中获得所有 method/class/type 信息。