Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 84 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,70 +1,109 @@
# CineTalk - Realtime Voice
# 🎬 CineTalk – Multi-Chatbot Voice Assistant

Aplicação de chat de voz em tempo real usando OpenAI Realtime API.
Aplicação web de **chat de voz em tempo real** com suporte a **OpenAI (ChatGPT)**, **Convai** e **Gemini**, permitindo conversas naturais, respostas faladas e recomendações de filmes com diferentes personalidades de assistente.

---

## 🚀 Deploy no GitHub Pages

Este site está hospedado no GitHub Pages: `https://beetools.github.io`
O projeto está hospedado em:
👉 **[https://beetools.github.io](https://beetools.github.io)**

---

## 🧩 Estrutura do Projeto

O código foi totalmente modularizado:

```
/index.html → estrutura base e containers
/css/style.css → estilos globais e temas
/js/main.js → controle da UI, troca de provedores e persistência de dados
/js/provider-chatgpt.js → integração com OpenAI API (ChatGPT)
/js/provider-gemini.js → integração futura com Gemini API
/js/provider-convai.js → integração com Convai (voz + Character ID)
```

### Configuração
Essa separação facilita a manutenção, depuração e adição de novos chatbots no futuro.

O repositório está configurado com:
- ✅ Arquivo `.nojekyll` para evitar processamento Jekyll
- ✅ Arquivo `index.html` na raiz do repositório
- ✅ Branch `main` como fonte do GitHub Pages
---

### Como atualizar o site
## 🤖 Chatbots Suportados

1. Faça suas alterações no `index.html`
2. Commit as mudanças:
| Provedor | API utilizada | Recursos principais |
|------------|---------------|--------------------|
| **ChatGPT** | OpenAI Realtime / Completions | Respostas rápidas com voz (TTS) e personalidade ajustável |
| **Convai** | Convai Character API | Personagem 3D com voz real e `Character ID` configurável |
| **Gemini** | Google Gemini API | Estrutura pronta para integração futura |

---

## ⚙️ Como Atualizar o Site

1. Faça suas alterações no repositório local:
```bash
git add .
git commit -m "Descrição das mudanças"
```
3. Envie para o GitHub:
```bash
git commit -m "feat: descrição das mudanças"
git push origin main
```
4. O GitHub Pages irá automaticamente fazer deploy das mudanças (geralmente leva de alguns segundos a 2 minutos)

### Verificar o status do deploy
2. O GitHub Pages fará o deploy automático (normalmente leva 1–2 minutos).

📍 **Status do deploy:**
[https://github.com/Beetools/beetools.github.io/actions](https://github.com/Beetools/beetools.github.io/actions)

---

## 🧠 Configuração e Uso

### 1. Selecione o provedor
No topo da página, escolha entre **ChatGPT**, **Gemini** ou **Convai**.

### 2. Configure suas credenciais
- Para ChatGPT: insira sua **OpenAI API Key**.
- Para Convai: insira a **Convai API Key** e o **Character ID**.

> 💡 As chaves são salvas localmente no navegador e não são compartilhadas.

### 3. Converse por texto ou voz
- Digite uma pergunta ou pressione o botão 🎤 para gravar sua fala.
- O assistente responderá em texto e/ou voz, conforme o provedor selecionado.

⚠️ **Importante:** em ambiente de produção, use **tokens efêmeros** e um **servidor intermediário** — nunca exponha suas chaves diretamente no front-end.

Acesse: `https://github.com/Beetools/beetools.github.io/actions`
---

## 📋 Sobre o Projeto
## 🎨 Funcionalidades

**CineTalk** é um assistente de cinema em tempo real que usa:
- OpenAI Realtime API para conversação por voz
- WebSocket para comunicação bidirecional
- VAD (Voice Activity Detection) no servidor
- Interface moderna e responsiva
- 💬 Chat de texto e voz com múltiplos provedores
- 🧠 Personalidade configurável (ChatGPT / Convai)
- 🎙️ Gravação e reprodução de áudio em tempo real
- 🔊 Visualizador de nível de áudio (VU meter)
- 📋 Copiar respostas
- 🧹 Limpar histórico
- 🎬 Sugestões de perguntas sobre cinema
- 🚫 Prevenção de mensagens duplicadas (Convai)

## 🔑 Configuração da API
---

Para usar a aplicação, você precisa de uma chave da OpenAI API:
1. Acesse o site
2. Insira sua API key no campo indicado
3. Segure o botão do microfone para falar
## 🛠️ Tecnologias Utilizadas

⚠️ **Aviso de Segurança**: Em produção, sempre use um token efêmero gerado no backend. Nunca exponha sua API key diretamente no browser.
- **HTML5**, **CSS3**, **JavaScript (Vanilla)**
- **OpenAI API**, **Convai API**, **Google Gemini API**
- **Web Audio API** (gravação, reprodução e visualização)
- **LocalStorage** (salvar chaves e configurações)
- **Axios** (requisições HTTP)
- **GitHub Pages** (deploy automático)

## 🎨 Recursos
---

- 🎤 Conversação por voz em tempo real
- 💬 Chat de texto alternativo
- 🎙️ Seleção de diferentes vozes
- 📊 Visualização de áudio em tempo real
- 💾 Histórico de conversas
- 📋 Copiar respostas
- 🎬 Sugestões de perguntas sobre cinema
## 📦 Estrutura de Branches

## 🛠️ Tecnologias
- `main` → versão estável e publicada
- `feat/multi-chatbot-architecture` → versão atual com modularização e novos provedores

- HTML5, CSS3, JavaScript (Vanilla)
- WebSocket API
- Web Audio API
- OpenAI Realtime API
---

## 📝 Licença
## 🧾 Licença

Este projeto é para fins educacionais e demonstração.
Este projeto é de uso **educacional e demonstrativo**, voltado a aplicações de IA generativa e interação por voz.
168 changes: 168 additions & 0 deletions css/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
:root{
--bg-0:#0b0d12; --bg-1:#0f1320; --bg-2:#131a2a;
--ink:#eaf6ff; --muted:#9fb3c8; --brand:#6366f1; --brand-2:#4f46e5; --warn:#f59e0b; --err:#ef4444;
--card:rgba(255,255,255,.04); --glass:rgba(255,255,255,.06);
--bd:rgba(255,255,255,.08); --bd-2:rgba(255,255,255,.12);
--radius:18px; --radius-sm:12px; --shadow:0 10px 40px rgba(0,0,0,.35);
}
html,body{height:100%}
body{
font-family: ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Ubuntu,"Helvetica Neue",Arial,"Noto Sans",sans-serif;
background:
radial-gradient(1200px 600px at 20% -10%, #1e1b4b, transparent),
radial-gradient(1200px 800px at 120% 0%, #312e81, transparent),
linear-gradient(135deg, #0b0d12 0%, #0f1320 50%, #131a2a 100%);
color:var(--ink);
line-height:1.6;
padding:16px;
}
a{color:var(--brand);text-decoration:none}
.container{max-width:1100px;margin:0 auto}

/* Header */
.appbar{
position:sticky;top:10px;z-index:20;
display:flex;align-items:center;gap:14px;justify-content:space-between;
padding:14px 18px;border-radius:16px;background:var(--glass);backdrop-filter: blur(12px);
border:1px solid var(--bd);box-shadow:var(--shadow);margin-bottom:16px;
}
.brand{display:flex;align-items:center;gap:12px}
.brand h1{
font-size:1.6rem;font-weight:800;
background:linear-gradient(135deg,var(--brand),#818cf8);
-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;
letter-spacing:.2px;text-shadow:0 0 24px rgba(99,102,241,.35);white-space:nowrap;
}

/* Provider switch */
.provider-switch{display:flex;gap:6px;align-items:center}
.provider-btn{
padding:8px 12px;border-radius:999px;border:1px solid var(--bd-2);
background:rgba(255,255,255,.02);color:var(--muted);cursor:pointer;font-size:.85rem;font-weight:600;
transition:.2s;
}
.provider-btn.active{
background:linear-gradient(135deg,var(--brand),var(--brand-2));
color:#fff;border:none;box-shadow:0 4px 14px rgba(99,102,241,.5);
}
.provider-btn:hover{transform:translateY(-1px)}

/* Conn */
.conn{
display:flex;align-items:center;gap:10px;padding:8px 12px;border-radius:999px;border:1px solid var(--bd);
background:var(--card)
}
.dot{width:10px;height:10px;border-radius:50%;background:#6b7280}
.dot.on{background:var(--brand);animation:dotPulse 2s infinite;box-shadow:0 0 10px var(--brand)}
@keyframes dotPulse{0%,100%{opacity:1}50%{opacity:.5}}

/* Panels */
.panel{
background:var(--card);border:1px solid var(--bd);border-radius:var(--radius);
padding:20px;backdrop-filter:blur(8px);box-shadow:var(--shadow);margin-bottom:16px;
}
.panel h2{font-size:1.05rem;color:var(--muted);margin-bottom:12px;letter-spacing:.2px}

.grid{display:grid;gap:12px}
@media (min-width:900px){.grid.cols-2{grid-template-columns:1.2fr .8fr}}

/* Inputs */
.field{display:grid;gap:8px}
.label{font-weight:700;color:var(--brand);font-size:.95rem}
.input{
width:100%;padding:14px;border-radius:12px;border:2px solid rgba(99,102,241,.28);
background:rgba(255,255,255,.04);color:var(--ink);outline:none;transition:.25s;font-size:1rem;
}
.input::placeholder{color:#98a9bd}
.input:focus{border-color:var(--brand);box-shadow:0 0 16px rgba(99,102,241,.25)}
.muted{color:var(--muted);font-size:.9rem}

/* Chat */
.chat{
height:520px;overflow:auto;padding:14px;border-radius:16px;
background:var(--glass);border:1px solid var(--bd)
}
.msg{
margin:12px 0;padding:14px 16px;border-radius:14px;position:relative;
box-shadow:0 6px 20px rgba(0,0,0,.25)
}
.msg.user{
background:linear-gradient(135deg,#667eea,#764ba2);
margin-left:15%;border-bottom-right-radius:6px
}
.msg.assistant{
background:linear-gradient(135deg,var(--brand),var(--brand-2));
margin-right:15%;border-bottom-left-radius:6px
}
.msg.system{
background:rgba(255,255,255,.08);color:#cbd5e1;font-style:italic;
border-left:3px solid var(--brand);margin:10px 5%
}
.time{
position:absolute;bottom:-18px;right:12px;
font-size:.72rem;color:#90a4b8;opacity:.85
}
.sticky-tip{font-size:.95rem;color:#c7d6e8;margin-bottom:6px}

/* Controls */
.controls{
display:flex;flex-direction:column;gap:12px;align-items:center;justify-content:center;
padding:18px;border-radius:16px;background:var(--glass);border:1px solid var(--bd)
}
.ptt{
width:140px;height:140px;border-radius:999px;border:none;cursor:pointer;font-size:2.2rem;
display:flex;align-items:center;justify-content:center;transition:.16s;
background:linear-gradient(135deg,var(--brand),var(--brand-2));color:#fff;
box-shadow:0 14px 36px rgba(99,102,241,.45)
}
.ptt:hover{transform:scale(1.05)}
.ptt.listening{background:linear-gradient(135deg,var(--warn),#f59e0b);animation:pttPulse 1.6s infinite}
@keyframes pttPulse{0%,100%{transform:scale(1)}50%{transform:scale(1.06)}}

.status{
text-align:center;font-weight:700;padding:12px 14px;border-radius:12px;
background:rgba(255,255,255,.05);border:2px solid transparent;width:100%
}
.status.ok{background:rgba(99,102,241,.15);border-color:var(--brand)}
.status.err{background:rgba(239,68,68,.15);border-color:var(--err)}

.meter{height:56px;display:flex;gap:6px;align-items:flex-end;justify-content:center}
.bar{width:6px;background:linear-gradient(to top,var(--brand),#818cf8);border-radius:3px;height:8px}

/* Footer */
.row{display:flex;gap:10px;flex-wrap:wrap}
.btn{
border:none;border-radius:10px;padding:12px 14px;font-weight:700;cursor:pointer;
background:rgba(255,255,255,.06);color:#e8f3ff;border:1px solid var(--bd-2);transition:.2s
}
.btn:hover{transform:translateY(-1px);box-shadow:0 6px 16px rgba(0,0,0,.25)}
.btn.primary{background:linear-gradient(135deg,var(--brand),var(--brand-2));border:none}
.btn.danger{background:linear-gradient(135deg,#ef4444,#dc2626);border:none}

/* Toasts */
.toast-wrap{
position:fixed;right:18px;bottom:18px;display:flex;flex-direction:column;gap:10px;z-index:99
}
.toast{
background:rgba(14,18,26,.9);color:#e9f4ff;padding:12px 14px;border:1px solid var(--bd);
border-radius:12px;box-shadow:var(--shadow);min-width:240px;font-size:.95rem
}

/* Suggestions */
.suggestions{display:grid;gap:10px}
.sugg{
background:rgba(255,255,255,.05);border:1px solid var(--bd);
padding:12px 14px;border-radius:12px;cursor:pointer
}
.sugg:hover{
background:rgba(99,102,241,.12);border-color:var(--brand);
transform:translateX(6px);transition:.18s
}

@media (max-width:780px){
.grid.cols-2{grid-template-columns:1fr}
.ptt{width:110px;height:110px}
.row{flex-direction:column}
.btn{width:100%}
}
Loading