private static async Task <SendFileResult> SendRawFile(string fileName) { // Create an Instance of the Archive Recording provider used to send archived audio to Tethr var tethrConnection = new TethrArchivedRecording(_tethrSession); // Figure out the file name of the sample file we are going to send to Tethr and read it in. using (var jsonStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { // Open the sample wave file. using (var wavStream = new FileStream(Path.ChangeExtension(fileName, ".wav"), FileMode.Open, FileAccess.Read, FileShare.Read)) { var reader = new StreamReader(jsonStream); // Send the audio and metadata to Tethr. var result = await _tethrSession.PostMultiPartAsync <ArchiveCallResponse>("/callCapture/v1/archive", reader.ReadToEnd(), wavStream, AudioMediaTypes.Wave); return(new SendFileResult { CallId = result.CallId, }); } } }
private static async Task <SendFileResult> SendFile(string fileName) { // Create an Instance of the Archive Recording provider used to send archived audio to Tethr var tethrConnection = new TethrArchivedRecording(_tethrSession); // Figure out the file name of the sample file we are going to send to Tethr and read it in. using (var jsonStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { var recording = jsonStream.JsonDeserialize <RecordingInfo>(); // NOTE: Session ID should be something that can be used by other systems to connect a call in Tethr // to the same call in other systems. The sessionID must be unique per recording. // // For this example, we are appending the time so we can test with the same file multiple times. // but should be a more meaningful value in production. recording.SessionId += DateTime.UtcNow.ToString("o"); // NOTE: it is important that the audio length and the reported call length are the same. // If this is not true, Tethr may have harder time accurately detecting what actually happened on a call // By default, Tethr will quarantine calls where the reported time and audio length do not match, and wait for // human interaction to fix any miss configurations. (Contact Support if you think you need this changed) // // for this example, we are Update the call times, so the calls don't always have the same time. // and if you change out the audio file in the sample, you will have to re-compute the end time in the sample JSON file. var audioLength = recording.EndTime - recording.StartTime; recording.StartTime = DateTime.UtcNow; recording.EndTime = recording.StartTime + audioLength; // Open the sample wave file. using (var wavStream = new FileStream(Path.ChangeExtension(fileName, ".wav"), FileMode.Open, FileAccess.Read, FileShare.Read)) { // Send the audio and metadata to Tethr. var result = await tethrConnection.SendRecordingAsync(recording, wavStream, AudioMediaTypes.Wave); return(new SendFileResult { CallId = result.CallId, SessionId = recording.SessionId, StartTime = recording.StartTime }); } } }
private void RefreshCallStateClick(object sender, RoutedEventArgs e) { var sessionId = this.SessionId.TextValueOrNull(); if (sessionId != null) { var hostUri = new Uri(this.UrlEndPoint.Text); var apiUser = ApiUserName.Text; var apiPassword = ApiPassword.SecurePassword; var status = Task.Run(async() => { try { // Because we are doing this in a UI, and that the setting can change from run to run // we are creating a new session per request. However, it is normaly recommended that session // be a singleton instanse per processes using (var session = new TethrSession(hostUri, apiUser, apiPassword)) { var archiveRecorder = new TethrArchivedRecording(session); return(await archiveRecorder.GetRecordingStatusAsync(sessionId)); } } catch (Exception exception) { MessageBox.Show(exception.Message, "Error sending call", MessageBoxButton.OK, MessageBoxImage.Error); return(null); } }).GetAwaiter().GetResult(); if (status != null) { CallId.Text = status.CallId; } CallState.Text = status?.Status.ToString() ?? "CALL NOT FOUND"; } }
private void StartUploadClicked(object sender, RoutedEventArgs e) { try { var audioFilePath = this.AudioFileName.Text; if (!File.Exists(audioFilePath)) { MessageBox.Show("Audio file not found.", "Error preping to send call", MessageBoxButton.OK, MessageBoxImage.Error); return; } var audioExt = Path.GetExtension(audioFilePath).ToLowerInvariant(); var audioType = (string)null; switch (audioExt) { case ".wav": audioType = "audio/x-wav"; break; case ".mp3": audioType = "audio/mp3"; break; case ".ogg": // TODO: we only support OPUS in Ogg, really should open the file and make sure it's OPUS. audioType = "audio/ogg"; break; default: MessageBox.Show(audioExt + " is not a supported audio file.", "Error preping to send call", MessageBoxButton.OK, MessageBoxImage.Error); return; } var settings = CreateRecordingInfo(); this.UploadBtn.IsEnabled = false; this.UploadProgress.Visibility = Visibility.Visible; var hostUri = new Uri(this.UrlEndPoint.Text); var apiUser = ApiUserName.Text; var apiPassword = ApiPassword.SecurePassword; Task.Run(async() => { try { // Because we are doing this in a UI, and that the setting can change from run to run // we are creating a new session per request. However, it is normaly recommended that session // be a singleton instanse per processes using (var session = new TethrSession(hostUri, apiUser, apiPassword)) { var archiveRecorder = new TethrArchivedRecording(session); using (var audioStream = File.OpenRead(audioFilePath)) { var result = await archiveRecorder.SendRecordingAsync(settings, audioStream, audioType); this.Dispatcher.Invoke(() => { this.CallId.Text = result.CallId; }); MessageBox.Show($"Call Upload Successful.\r\n\r\nCall ID : {result.CallId}", "Call Uploaded", MessageBoxButton.OK, MessageBoxImage.Information); } } } catch (Exception exception) { MessageBox.Show(exception.Message, "Error sending call", MessageBoxButton.OK, MessageBoxImage.Error); } finally { this.Dispatcher.Invoke(() => { this.UploadBtn.IsEnabled = true; this.UploadProgress.Visibility = Visibility.Collapsed; }); } }); } catch (Exception exception) { this.UploadBtn.IsEnabled = true; this.UploadProgress.Visibility = Visibility.Collapsed; MessageBox.Show(exception.Message, "Error preping to send call", MessageBoxButton.OK, MessageBoxImage.Error); } }