File size: 4,377 Bytes
e73e4ff
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c884a22
e73e4ff
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c573c6e
e73e4ff
 
 
 
 
d241d01
 
cc2ede4
d241d01
4f54a6c
 
 
d241d01
 
 
 
c884a22
c573c6e
e73e4ff
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c884a22
e73e4ff
 
 
c884a22
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
from groq import Groq
from pydantic import BaseModel, ValidationError
from typing import List, Literal
import os
import tiktoken
import json
import re
import tempfile
from gtts import gTTS
from bs4 import BeautifulSoup
import requests

groq_client = Groq(api_key=os.environ["GROQ_API_KEY"])
tokenizer = tiktoken.get_encoding("cl100k_base")

class DialogueItem(BaseModel):
    speaker: Literal["Priya", "Ananya"]
    text: str

class Dialogue(BaseModel):
    dialogue: List[DialogueItem]

def truncate_text(text, max_tokens=2048):
    tokens = tokenizer.encode(text)
    if len(tokens) > max_tokens:
        return tokenizer.decode(tokens[:max_tokens])
    return text

def extract_text_from_url(url):
    try:
        response = requests.get(url)
        response.raise_for_status()
        soup = BeautifulSoup(response.text, 'html.parser')
        
        for script in soup(["script", "style"]):
            script.decompose()
        
        text = soup.get_text()
        lines = (line.strip() for line in text.splitlines())
        chunks = (phrase.strip() for line in lines for phrase in line.split("  "))
        text = '\n'.join(chunk for chunk in chunks if chunk)
        
        return text
    except Exception as e:
        raise ValueError(f"Error extracting text from URL: {str(e)}")

def generate_script(system_prompt: str, input_text: str, tone: str, target_length: str):
    input_text = truncate_text(input_text)
    word_limit = 300 if target_length == "Short (1-2 min)" else 750
    
    prompt = f"""
    {system_prompt}
    TONE: {tone}
    TARGET LENGTH: {target_length} (approximately {word_limit} words)
    INPUT TEXT: {input_text}
    Generate a complete, well-structured podcast script that:
    1. Starts with a proper introduction, welcoming listeners in an engaging and friendly way.
    2. Covers the main points from the input text in a natural, conversational manner.
    3. Has a smooth,soft, engaging flow of conversation between Priya (American accent) and Ananya (British accent) like real human intraction.
    4. Concludes with a well-rounded summary and sign-off, thanking the listeners.
    5. voice speed will be according to the converstion and topic , easy to unserstand every listeners.
    6. Fits within the {word_limit} word limit for the target length of {target_length}.
    7. Strongly emphasizes the {tone} tone throughout the conversation.
    For a humorous tone, include jokes, puns, and playful banter, incorporating Indian references or light-hearted cultural humor.
    For a casual tone, use colloquial language, friendly expressions, and references to popular culture, making it feel like a relaxed conversation between friends.
    For a formal tone, maintain a professional podcast style with clear, well-structured arguments and formal language, showing respect and politeness.
    Ensure the script is well-structured and forms a complete, cohesive conversation without any abrupt ending.
    """
    
    response = groq_client.chat.completions.create(
        messages=[
            {"role": "system", "content": prompt},
        ],
        model="llama-3.1-70b-versatile",
        max_tokens=2048,
        temperature=0.7
    )
    
    content = response.choices[0].message.content
    content = re.sub(r'```json\s*|\s*```', '', content)
    
    try:
        json_data = json.loads(content)
        dialogue = Dialogue.model_validate(json_data)
    except json.JSONDecodeError as json_error:
        match = re.search(r'\{.*\}', content, re.DOTALL)
        if match:
            try:
                json_data = json.loads(match.group())
                dialogue = Dialogue.model_validate(json_data)
            except (json.JSONDecodeError, ValidationError) as e:
                raise ValueError(f"Failed to parse dialogue JSON: {e}\nContent: {content}")
        else:
            raise ValueError(f"Failed to find valid JSON in the response: {content}")
    except ValidationError as e:
        raise ValueError(f"Failed to validate dialogue structure: {e}\nContent: {content}")
    
    return dialogue

def generate_audio(text: str, speaker: str) -> str:
    tld = 'com' if speaker == "Priya" else 'co.in'
    tts = gTTS(text=text, lang='en', tld=tld)
    with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as temp_audio:
        tts.save(temp_audio.name)
        return temp_audio.name