-
Notifications
You must be signed in to change notification settings - Fork 43
Add API request for generate audio using Microsoft Edge's online text-to-speech service #31
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
base: main
Are you sure you want to change the base?
Conversation
WalkthroughThe changes involve updates to the Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant API
participant TTSService
Client->>API: GET /voices
API->>TTSService: List available voices
TTSService-->>API: Return voices list
API-->>Client: Return voices list
Client->>API: POST /tts with TTSRequest
API->>TTSService: Process TTS request
TTSService-->>API: Generate audio
API-->>Client: Return audio in WAV format
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
Outside diff range and nitpick comments (1)
pyproject.toml (1)
39-39
: Consider specifying the version of the dependency.To ensure compatibility in the future, it's a good practice to specify the version of the dependency. For example:
- "edge-tts", + "edge-tts==1.0.0",
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (3)
- pyproject.toml (1 hunks)
- requirements.txt (1 hunks)
- rvc_python/api.py (3 hunks)
Additional context used
Ruff
rvc_python/api.py
159-159: Within an
except
clause, raise exceptions withraise ... from err
orraise ... from None
to distinguish them from errors in exception handling(B904)
Additional comments not posted (3)
requirements.txt (2)
18-18
: LGTM!The addition of the
python-multipart
dependency aligns with the PR objectives. It is a commonly used library for handling multipart form data in web applications and APIs, particularly for file uploads.Given that the PR involves an API request for generating audio, it is reasonable to assume that this dependency will be used to send audio files or data to the API.
19-19
: Looks good!The
edge-tts
dependency is a great fit for the PR objectives. It provides a Python interface to interact with Microsoft Edge's online text-to-speech service, which is exactly what the PR aims to achieve.By adding this dependency, the project gains the ability to convert text to speech using the various voices provided by the Edge TTS service. This aligns perfectly with the goal of generating audio using Microsoft's service.
pyproject.toml (1)
39-39
: LGTM!The addition of the
edge-tts
dependency is consistent with the PR objectives and is necessary to support the new feature.
|
||
class TTSRequest(BaseModel): | ||
text: str | ||
voice: str | None = "Microsoft Server Speech Text to " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Complete the default value for voice
in TTSRequest
The default value for voice
appears incomplete: "Microsoft Server Speech Text to "
. Please provide a complete and valid default voice identifier to ensure the TTS service functions correctly.
Apply this diff to fix the default voice
value:
- voice: str | None = "Microsoft Server Speech Text to "
+ voice: str | None = "en-US-AriaNeural"
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
voice: str | None = "Microsoft Server Speech Text to " | |
voice: str | None = "en-US-AriaNeural" |
@app.get("/voices") | ||
async def list_voices(): | ||
return JSONResponse(content={"voices": await edge_tts.list_voices()}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add exception handling to the /voices
endpoint
Currently, the list_voices
endpoint does not handle exceptions that may occur when calling edge_tts.list_voices()
. This could lead to unhandled exceptions and a 500 Internal Server Error response without meaningful information to the client. Consider adding error handling to provide a clear error message.
Apply this diff to incorporate exception handling:
@app.get("/voices")
async def list_voices():
+ try:
voices = await edge_tts.list_voices()
return JSONResponse(content={"voices": voices})
+ except Exception as e:
+ logger.error(f"Error retrieving voices: {e}")
+ raise HTTPException(status_code=500, detail="Failed to retrieve voices.") from e
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
@app.get("/voices") | |
async def list_voices(): | |
return JSONResponse(content={"voices": await edge_tts.list_voices()}) | |
@app.get("/voices") | |
async def list_voices(): | |
try: | |
voices = await edge_tts.list_voices() | |
return JSONResponse(content={"voices": voices}) | |
except Exception as e: | |
logger.error(f"Error retrieving voices: {e}") | |
raise HTTPException(status_code=500, detail="Failed to retrieve voices.") from e |
) | ||
await communicate.save(input_path) | ||
|
||
app.state.rvc.infer_file(input_path, output_path) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid blocking the event loop with synchronous infer_file
method
The app.state.rvc.infer_file
method appears to be a synchronous and potentially long-running operation. Executing it directly in an async endpoint could block the event loop, affecting the application's performance. Consider running it in a separate thread using asyncio.to_thread
.
Apply this diff to run infer_file
without blocking:
- app.state.rvc.infer_file(input_path, output_path)
+ await asyncio.to_thread(app.state.rvc.infer_file, input_path, output_path)
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
app.state.rvc.infer_file(input_path, output_path) | |
await asyncio.to_thread(app.state.rvc.infer_file, input_path, output_path) |
|
||
app.state.rvc.infer_file(input_path, output_path) | ||
|
||
output_data = tmp_output.read() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reset the file pointer before reading tmp_output
After writing to tmp_output
, the file pointer is at the end of the file. Before reading from it, you need to reset the file pointer to the beginning using tmp_output.seek(0)
; otherwise, output_data
may be empty.
Apply this diff to reset the file pointer:
tmp_output.close()
+ tmp_output = open(output_path, 'rb')
+ output_data = tmp_output.read()
+ tmp_output.close()
Alternatively, seek to the beginning before reading:
tmp_output.seek(0)
output_data = tmp_output.read()
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
output_data = tmp_output.read() | |
tmp_output.seek(0) | |
output_data = tmp_output.read() |
return Response(content=output_data, media_type="audio/wav") | ||
except Exception as e: | ||
logger.error(e) | ||
raise HTTPException(status_code=500, detail=f"An error occurred: {str(e)}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Chain exceptions when raising HTTPException
When raising a new exception within an except
block, it's good practice to chain it using from e
to preserve the original traceback. This helps in distinguishing exceptions in error handling from those in the main code.
Apply this diff to chain exceptions:
logger.error(e)
- raise HTTPException(status_code=500, detail=f"An error occurred: {str(e)}")
+ raise HTTPException(status_code=500, detail=f"An error occurred: {str(e)}") from e
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
raise HTTPException(status_code=500, detail=f"An error occurred: {str(e)}") | |
raise HTTPException(status_code=500, detail=f"An error occurred: {str(e)}") from e |
Tools
Ruff
159-159: Within an
except
clause, raise exceptions withraise ... from err
orraise ... from None
to distinguish them from errors in exception handling(B904)
Summary by CodeRabbit
New Features
Dependencies
fastapi
,pydantic
,python-multipart
, andedge-tts
for enhanced application capabilities.