rust-racs is the rust client library for RACS. It provides access to all the RACS commands through a low-level API.
Run the following Cargo command in your project directory:
cargo add racs
Or add the following line to your Cargo.toml:
racs = "0.1.1"
To open a connection, simply create a client using open.
use racs::Client;
let client = Client::open("127.0.0.1:6381").unwrap();The open function creates a client with a default connection pool size of 3.
To specify the connection pool size, use open_with_pool_size.
use racs::Client;
let client = Client::open_with_pool_size("127.0.0.1:6381", 5).unrwap();The pipeline function is used to chain together multiple RACS commands and execute them sequentially.
In the below example, a new audio stream is created and opened. Then PCM data is chunked into frames
and streamed to the RACS server.
use racs::Client;
// Connect to a RACS server
let client = Client::open("127.0.0.1:6381").unwrap();
// Create a new audio stream and open it using pipeline
client
.pipeline()
.create(
"Beethoven Piano Sonata No.1", // stream name
44100, // sample rate (Hz)
2, // number of channels
16, // bit depth
)
.open("Beethoven Piano Sonata No.1")
.execute() // execute all pipelined commands
.unwrap();
// Prepare PCM samples (interleaved L/R, 16- or 24-bit integers)
let samples: Vec<i32> = /* your PCM audio data */;
// Stream audio data to the server
client
.stream(
"Beethoven Piano Sonata No.1",
1024 * 32, // chunk size (32 KB)
samples.as_slice(), // PCM samples
)
.unwrap();
// Close the stream when finished
client
.pipeline()
.close("Beethoven Piano Sonata No.1")
.execute()
.unwrap();The below example retrieves a reference timestamp, and uses it to extract an audio segment based on the given range. It then converts the extracted PCM data into MP3 format and writes the resulting bytes to a file.
use chrono::{Days, TimeZone, Utc};
use racs::Client;
use racs::Type;
use std::fs::File;
use std::io::Write;
// Connect to the RACS server
let client = Client::open("127.0.0.1:6381").unwrap();
// Get the reference timestamp (in milliseconds)
let result = client
.pipeline()
.info("Beethoven Piano Sonata No.1", "ref")
.execute();
if let Type::Int(ref_ms) = result.unwrap() {
// Convert milliseconds to DateTime<Utc>
let from = Utc.timestamp_millis_opt(ref_ms).unwrap();
// Compute end time by adding one day
let to = from
.checked_add_days(Days::new(1))
.unwrap();
// Extract PCM data between `from` and `to`
// Convert (format) the audio to MP3
let result = client
.pipeline()
.extract("Beethoven Piano Sonata No.1", from, to)
.format(
"audio/mp3", // mime-type
44100, // sample rate (Hz)
2, // number of channels
16 // bit depth
)
.execute();
if let Type::U8V(data) = result.unwrap() {
// Use or save the MP3 bytes
// e.g. write them to a file
let mut file = File::create("beethoven.mp3").unwrap();
file.write_all(&data).unwrap();
}
}To extract PCM data without formating, do the following instead:
// Extract PCM data between `from` and `to`
let result = client
.pipeline()
.extract("Beethoven Piano Sonata No.1", from, to)
.execute();
if let Type::S32V(data) = result.unwrap() {
// Use PCM samples stored in data: Vec<i32>
}Stream ids stored in RACS can be queried using the search function.
search takes a glob pattern and returns a vector of streams ids matching the pattern.
use racs::Client;
use racs::Type;
// Connect to the RACS server
let client = Client::open("127.0.0.1:6381").unwrap();
// Run list command matching "*" pattern
let result = client
.pipeline()
.search("*")
.execute();
// Print the list of stream ids
if let Type::List(list) = result.unwrap() {
// [String("Beethoven Piano Sonata No.1")]
println!("{:?}", list);
}Note
String is the only element type currently supported for Type::List
Stream metadata can be queried using the info function.
info takes the stream id and metadata attribute as parameters.
use racs::Client;
use racs::Type;
// Connect to the RACS server
let client = Client::open("127.0.0.1:6381").unwrap();
// Get sample rate attribute for stream
let result = client
.pipeline()
.info("Beethoven Piano Sonata No.1", "sample_rate")
.execute();
// Print the sample rate
if let Type::Int(sample_rate) = result.unwrap() {
println!("{:?}", sample_rate);
}i64 is returned for all metadata attributes. The supported attributes are:
| Attribute | Description |
|---|---|
channels |
Channel count of the audio stream. |
sample_rate |
Sample rate of the audio stream (Hz). |
bit_depth |
Bit depth of the audio stream. |
ref |
Reference timestamp (milliseconds UTC). |
size |
Size of audio stream in bytes. |
To execute raw command strings, use the execute_command function.
use racs::Client;
use racs::Type;
let client = Client::open("127.0.0.1:6381").unwrap();
let result = client.execute_command("EVAL '(+ 1 2 3)'");
if let Type::Int(num) = result.unwrap() {
}Refer to the documentation in RACS for the commands.
Below is a table of conversions for the Type enum between RACS and rust:
| RACS | Rust |
|---|---|
Type::Int |
i64 |
Type::Float |
f64 |
Type::Bool |
bool |
Type::String |
String |
Type::Error |
Err |
Type::Null |
N/A |
Type::U8V |
Vec<u8> |
Type::U16V |
Vec<u16> |
Type::S16V |
Vec<i16> |
Type::U32V |
Vec<u32> |
Type::S32V |
Vec<i32> |
Type::C64V |
Vec<Complex32> |
Type::List |
Vec<Type> |