Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update screencapturekit-rs #181

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 123 additions & 14 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ futures-util = "0.3.30"
# serve audio
urlencoding = "2.1.3"
# screencapturekit = "0.2.8"
# fix thread crash
# screencapturekit = { git = "https://github.com/doom-fish/screencapturekit-rs", rev = "8829f70"}
screencapturekit = { git = "https://github.com/solaoi/screencapturekit-rs" }
screencapturekit = { git = "https://github.com/doom-fish/screencapturekit-rs", rev = "3582a58"}
core-media-rs = { git = "https://github.com/doom-fish/core-frameworks.git" }

xcap = "0.0.14"
# permission
macos-accessibility-client = "0.0.1"
Expand Down
99 changes: 46 additions & 53 deletions src-tauri/src/module/record_desktop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,33 +25,27 @@ use crossbeam_channel::{unbounded, Receiver, Sender};
use hound::{WavSpec, WavWriter};
use tauri::{api::path::data_dir, AppHandle, Manager};

use core_media_rs::cm_sample_buffer::CMSampleBuffer;
use screencapturekit::{
cm_sample_buffer::CMSampleBuffer,
sc_content_filter::{InitParams, SCContentFilter},
sc_error_handler::StreamErrorHandler,
sc_output_handler::{SCStreamOutputType, StreamOutput},
sc_shareable_content::SCShareableContent,
sc_stream::SCStream,
sc_stream_configuration::SCStreamConfiguration,
shareable_content::SCShareableContent,
stream::{
configuration::SCStreamConfiguration, content_filter::SCContentFilter,
output_trait::SCStreamOutputTrait, output_type::SCStreamOutputType, SCStream,
},
};

use vosk::Recognizer;

use super::{
chat_online, recognizer::MyRecognizer, sqlite::Sqlite, transcription, transcription_amivoice, transcription_ja, transcription_online, translation_en, translation_ja, translation_ja_high, writer::Writer
chat_online, recognizer::MyRecognizer, sqlite::Sqlite, transcription, transcription_amivoice,
transcription_ja, transcription_online, translation_en, translation_ja, translation_ja_high,
writer::Writer,
};

pub struct RecordDesktop {
app_handle: AppHandle,
}

struct ErrorHandler;
impl StreamErrorHandler for ErrorHandler {
fn on_error(&self) {
println!("Error!");
}
}

struct StoreAudioHandler {
app_handle: AppHandle,
recognizer: Weak<Mutex<Recognizer>>,
Expand All @@ -60,32 +54,34 @@ struct StoreAudioHandler {
channels: u16,
}

impl StreamOutput for StoreAudioHandler {
impl SCStreamOutputTrait for StoreAudioHandler {
fn did_output_sample_buffer(&self, sample: CMSampleBuffer, _of_type: SCStreamOutputType) {
let audio_buffers = sample.sys_ref.get_av_audio_buffer_list();
let audio_buffers = sample.get_audio_buffer_list();
if audio_buffers.is_err() {
println!("Error getting audio buffer list");
}
let bytes = &audio_buffers.unwrap()[0].data; // 最初のチャンネルのデータを選択
if let Some(buffer) = audio_buffers.unwrap().get(0) {
let bytes = &buffer.data();

// バッファのデータを直接処理
let samples: Vec<f32> = bytes
.chunks_exact(4)
.map(|chunk| f32::from_le_bytes(chunk.try_into().unwrap()))
.collect();
// バッファのデータを f32 に変換
let samples: Vec<f32> = bytes
.chunks_exact(4)
.map(|chunk| f32::from_le_bytes(chunk.try_into().unwrap()))
.collect();

if let Some(recognizer) = self.recognizer.upgrade() {
MyRecognizer::recognize(
self.app_handle.clone(),
&mut recognizer.lock().unwrap(),
&samples,
self.channels,
self.notify_decoding_state_is_finalized_tx.clone(),
true,
);
}
if let Some(recognizer) = self.recognizer.upgrade() {
MyRecognizer::recognize(
self.app_handle.clone(),
&mut recognizer.lock().unwrap(),
&samples,
self.channels,
self.notify_decoding_state_is_finalized_tx.clone(),
true,
);
}

Writer::write_input_data::<f32, f32>(&samples, &self.writer_clone);
Writer::write_input_data::<f32, f32>(&samples, &self.writer_clone);
}
}
}

Expand All @@ -102,32 +98,29 @@ impl RecordDesktop {
stop_record_rx: Receiver<()>,
stop_record_clone_tx: Option<Sender<()>>,
) {
let mut current = SCShareableContent::current();
let display = current.displays.pop().unwrap();
let display = SCShareableContent::get().unwrap().displays().remove(0);

let channels = 1 as u16;
let channels = 1 as u8;
// the system uses a default sample rate of 48 kHz.
// https://developer.apple.com/documentation/screencapturekit/scstreamconfiguration/3931903-samplerate
let sample_rate = 48000;
let bits_per_sample = 32;
let config = SCStreamConfiguration {
width: 100,
height: 100,
captures_audio: true,
sample_rate,
channel_count: channels as u32,
excludes_current_process_audio: true,
..Default::default()
};

let config = SCStreamConfiguration::new()
.set_captures_audio(true)
.unwrap()
.set_channel_count(channels)
.unwrap();

let recognizer = MyRecognizer::build(
self.app_handle.clone(),
speaker_language.clone(),
config.sample_rate as f32,
sample_rate as f32,
);
let recognizer_arc = Arc::new(Mutex::new(recognizer));
let recognizer_weak = Arc::downgrade(&recognizer_arc);

let spec = WavSpec {
channels,
channels: channels as u16,
sample_rate,
bits_per_sample,
sample_format: hound::SampleFormat::Float,
Expand All @@ -145,15 +138,15 @@ impl RecordDesktop {
let (notify_decoding_state_is_finalized_tx, notify_decoding_state_is_finalized_rx) =
sync_channel(1);
let app_handle = self.app_handle.clone();
let filter = SCContentFilter::new(InitParams::Display(display));
let mut stream = SCStream::new(filter, config, ErrorHandler);
stream.add_output(
let filter = SCContentFilter::new().with_display_excluding_windows(&display, &[]);
let mut stream = SCStream::new(&filter, &config);
stream.add_output_handler(
StoreAudioHandler {
app_handle,
recognizer: recognizer_weak,
notify_decoding_state_is_finalized_tx,
writer_clone,
channels,
channels: channels as u16,
},
SCStreamOutputType::Audio,
);
Expand Down