File size: 3,731 Bytes
ddb099d
0925810
3a9a0d8
ddb099d
 
 
c2260d3
ddb099d
 
 
c2fa877
 
ddb099d
 
3a9a0d8
 
 
 
 
 
 
 
c2fa877
 
 
 
 
0925810
ddb099d
c2fa877
 
 
ddb099d
c2fa877
 
 
ddb099d
 
c2fa877
 
 
 
 
 
 
ddb099d
c2fa877
c2260d3
 
1decf45
c2260d3
c2fa877
 
 
 
 
c2260d3
ddb099d
c2fa877
 
c2260d3
 
 
 
ddb099d
 
 
 
 
 
 
c2260d3
c2fa877
 
 
ddb099d
 
1decf45
c2fa877
 
 
ddb099d
 
 
 
c2260d3
c2fa877
 
 
 
c2260d3
 
 
 
 
 
c2fa877
 
 
 
 
c2260d3
 
 
 
1decf45
ddb099d
c2fa877
ddb099d
 
c2260d3
1decf45
c2260d3
c2fa877
c2260d3
 
 
 
1decf45
c2260d3
 
 
ddb099d
3a9a0d8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import os
from pathlib import Path
from typing import List

import gradio as gr
from dotenv import load_dotenv
from langchain_community.document_loaders import PyPDFLoader

load_dotenv()

from src.builder import AudiobookBuilder
from src.config import logger, FILE_SIZE_MAX


def get_auth_params() -> List[tuple[str, str]]:
    users = os.environ["AUTH_USERS"].split(",")
    passwords = os.environ["AUTH_PASS"].split(",")

    auth_list = [(u, passwords[0] if len(passwords) == 1 else p) for u, p in zip(users, passwords)]
    return auth_list


def parse_pdf(file_path):
    """Parse the PDF file and return the text content."""
    loader = PyPDFLoader(file_path)
    documents = loader.load()
    return "\n".join([doc.page_content for doc in documents])


def load_text_from_file(uploaded_file):
    # Save the uploaded file temporarily to check its size
    temp_file_path = uploaded_file.name

    if os.path.getsize(temp_file_path) > FILE_SIZE_MAX * 1024 * 1024:
        raise ValueError(
            f"The uploaded file exceeds the size limit of {FILE_SIZE_MAX} MB."
        )

    if uploaded_file.name.endswith(".txt"):
        with open(temp_file_path, "r", encoding="utf-8") as file:
            text = file.read()
    elif uploaded_file.name.endswith(".pdf"):
        text = parse_pdf(temp_file_path)
    else:
        raise ValueError("Unsupported file type. Please upload a .txt or .pdf file.")

    return text


async def respond(text: str, uploaded_file) -> tuple[Path | None, str]:
    if uploaded_file is not None:
        try:
            text = load_text_from_file(uploaded_file=uploaded_file)
        except Exception as e:
            logger.exception(e)
            return (None, str(e))

    builder = AudiobookBuilder()
    audio_fp = await builder.run(text=text)
    return audio_fp, ""


def refresh():
    return None, None, None  # Reset audio output, error message, and uploaded file


with gr.Blocks(title="Audiobooks Generation") as ui:
    gr.Markdown("# Audiobooks Generation")

    with gr.Row(variant="panel"):
        text_input = gr.Textbox(label="Enter the book text", lines=20)
        # Add a file upload field for .txt and .pdf files
        file_input = gr.File(
            label="Upload a text file or PDF", file_types=[".txt", ".pdf"]
        )

    with gr.Row(variant="panel"):
        audio_output = gr.Audio(label="Generated audio", type="filepath")
        error_output = gr.Textbox(
            label="Error Messages", interactive=False, visible=False
        )  # Initially hidden

    submit_button = gr.Button("Submit")
    submit_button.click(
        fn=respond,
        inputs=[text_input, file_input],  # Include the uploaded file as an input
        outputs=[
            audio_output,
            error_output,
        ],  # Include the audio output and error message output
    )

    refresh_button = gr.Button("Refresh")
    refresh_button.click(
        fn=refresh,
        inputs=[],
        outputs=[
            audio_output,
            error_output,
            file_input,
        ],  # Reset audio output, error message, and uploaded file
    )

    # Hide error message dynamically when input is received
    text_input.change(
        fn=lambda _: gr.update(visible=False),  # Hide the error field
        inputs=[text_input],
        outputs=error_output,
    )

    file_input.change(
        fn=lambda _: gr.update(visible=False),  # Hide the error field
        inputs=[file_input],
        outputs=error_output,
    )

    # To clear error field when refreshing
    refresh_button.click(
        fn=lambda _: gr.update(visible=False),  # Hide the error field
        inputs=[],
        outputs=error_output,
    )

ui.launch(auth=get_auth_params())