diff --git a/tts_service/src/endpoints/legacy_speak.rs b/tts_service/src/endpoints/legacy_speak.rs index c9ba87b84c..c9d6b0f47c 100644 --- a/tts_service/src/endpoints/legacy_speak.rs +++ b/tts_service/src/endpoints/legacy_speak.rs @@ -1,9 +1,6 @@ -use actix_web::http::StatusCode; +use actix_web::http::{StatusCode, header}; use actix_web::web::{Data, Query}; -use actix_web::{ - HttpRequest, - HttpResponse, -}; +use actix_web::{HttpRequest, HttpResponse}; use std::sync::Arc; use crate::AppState; @@ -146,8 +143,21 @@ pub async fn legacy_get_speak(request: HttpRequest, segfaults are fixed.")) }, Some(wav_data) => { + // To make iOS Safari work, you need a Content-Range and Content-Length header: + // https://stackoverflow.com/a/17835399 + // Content-Range: bytes XX-XX/XX + // Content-Type: audio/wav + // Content-Disposition: attachment; filename = "new.WAV" + // Content-Length: XX + // + // Content-Range: bytes */* + // Content-Type: audio/wav + // Content-Disposition: + // Content-Length: len() Ok(HttpResponse::build(StatusCode::OK) .content_type("audio/wav") + .set_header(header::CONTENT_DISPOSITION, "attachment; filename = \"generated.wav\"") + .set_header(header::CONTENT_RANGE, "bytes */*") .body(wav_data)) }, } @@ -188,8 +198,21 @@ pub async fn legacy_get_speak(request: HttpRequest, let wav_data = arpabet_glow_tts_melgan_pipeline(&cleaned_text, &glow_tts, &melgan); + // To make iOS Safari work, you need a Content-Range and Content-Length header: + // https://stackoverflow.com/a/17835399 + // Content-Range: bytes XX-XX/XX + // Content-Type: audio/wav + // Content-Disposition: attachment; filename = "new.WAV" + // Content-Length: XX + // + // Content-Range: bytes */* + // Content-Type: audio/wav + // Content-Disposition: + // Content-Length: len() Ok(HttpResponse::build(StatusCode::OK) .content_type("audio/wav") + .set_header(header::CONTENT_DISPOSITION, "attachment; filename = \"generated.wav\"") + .set_header(header::CONTENT_RANGE, "bytes */*") .body(wav_data)) }, ModelPipeline::RawTextTacotronMelgan => unimplemented!(), diff --git a/tts_service/src/endpoints/speak.rs b/tts_service/src/endpoints/speak.rs index 8589ef578d..f417e27634 100644 --- a/tts_service/src/endpoints/speak.rs +++ b/tts_service/src/endpoints/speak.rs @@ -1,4 +1,4 @@ -use actix_web::http::StatusCode; +use actix_web::http::{StatusCode, header}; use actix_web::web::{ Data, Json, @@ -105,8 +105,12 @@ pub async fn post_speak(request: HttpRequest, segfaults are fixed.")) }, Some(wav_data) => { + // To make iOS Safari work, you need a Content-Range and Content-Length header: + // https://stackoverflow.com/a/17835399 Ok(HttpResponse::build(StatusCode::OK) .content_type("audio/wav") + .set_header(header::CONTENT_DISPOSITION, "attachment; filename = \"generated.wav\"") + .set_header(header::CONTENT_RANGE, "bytes */*") .body(wav_data)) }, } @@ -134,8 +138,12 @@ pub async fn post_speak(request: HttpRequest, let wav_data = arpabet_glow_tts_melgan_pipeline(&cleaned_text, &glow_tts, &melgan); + // To make iOS Safari work, you need a Content-Range and Content-Length header: + // https://stackoverflow.com/a/17835399 Ok(HttpResponse::build(StatusCode::OK) .content_type("audio/wav") + .set_header(header::CONTENT_DISPOSITION, "attachment; filename = \"generated.wav\"") + .set_header(header::CONTENT_RANGE, "bytes */*") .body(wav_data)) }, ModelPipeline::RawTextTacotronMelgan => unimplemented!(),