Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
BarryYin committed Dec 18, 2024
1 parent c67103d commit c4b5c3b
Show file tree
Hide file tree
Showing 8 changed files with 1,366 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# OPENAI_API_KEY=你的OpenAI API密钥
OPENAI_API_KEY=sk-你的OpenAI API密钥
# 设置代理服务器地址
HTTP_PROXY=http://127.0.0.1:26001
HTTPS_PROXY=http://127.0.0.1:26001
96 changes: 92 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,97 @@
# openai-Realtime-API-with-WebRTC
openai-Realtime-API-with-WebRTC
# WebRTC OpenAI 实时通信应用

Coming soon
这是一个使用 WebRTC 技术与 OpenAI API 进行实时通信的 Web 应用程序。该应用支持通过数据通道与 OpenAI 进行实时数据交换。

the app with the openai-Realtime-API-with-WebRTC
## 功能特点

- 使用 WebRTC 建立点对点连接
- 集成 OpenAI API
- 支持代理设置,解决网络访问问题
- 实时数据通信
- 简洁的用户界面

## 技术栈

- Node.js
- Express.js
- WebRTC
- OpenAI API
- WebSocket

## 前置要求

- Node.js 18.0.0 或更高版本
- npm 包管理器
- OpenAI API 密钥
- 可用的代理服务器(如果需要)

## 安装步骤

1. 克隆仓库:
```bash
git clone https://github.com/BarryYin/openai-Realtime-API-with-WebRTC.git
cd openai-Realtime-API-with-WebRTC
```

2. 安装依赖:
```bash
npm install
```

3. 配置环境变量:
- 复制 `.env.example` 文件为 `.env`
-`.env` 文件中设置你的 OpenAI API 密钥和代理设置:
```
OPENAI_API_KEY=你的OpenAI API密钥
HTTP_PROXY=http://127.0.0.1:你的代理端口
HTTPS_PROXY=http://127.0.0.1:你的代理端口
```
## 运行应用
1. 启动服务器:
```bash
npm start
```

2. 在浏览器中打开:
```
http://localhost:3000
```

## 使用说明

1. 打开应用后,点击"开始连接"按钮建立 WebRTC 连接
2. 连接成功后,状态会显示"已连接"
3. 使用"发送测试消息"按钮测试通信
4. 需要断开连接时,点击"断开连接"按钮

## 文件结构

- `getapi.js`: Express 服务器和 OpenAI API 集成
- `init.js`: WebRTC 连接初始化和管理
- `main.js`: 数据通道通信逻辑
- `index.html`: 用户界面
- `.env`: 环境变量配置

## 注意事项

- 确保 OpenAI API 密钥有效且有足够的配额
- 如果遇到连接问题,检查代理设置是否正确
- 保持浏览器控制台打开以查看详细日志

## 故障排除

1. 连接超时
- 检查 API 密钥是否正确
- 确认代理服务器是否正常运行
- 验证网络连接是否稳定

2. 发送消息失败
- 确保 WebRTC 连接已建立
- 检查数据通道是否开启
- 查看浏览器控制台是否有错误信息

## License

ISC
113 changes: 113 additions & 0 deletions getapi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import express from "express";
import dotenv from "dotenv";
import { fileURLToPath } from 'url';
import { dirname } from 'path';
import path from 'path';
import fetch from 'node-fetch';
import https from 'https';
import { HttpsProxyAgent } from 'https-proxy-agent';

// 获取当前文件的目录路径
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

// 加载环境变量
dotenv.config();

const app = express();

// 创建自定义的 HTTPS agent,设置更长的超时时间
const httpsAgent = new https.Agent({
timeout: 30000, // 30 秒超时
keepAlive: true
});

// 创建代理 agent
const proxyUrl = process.env.HTTPS_PROXY || process.env.HTTP_PROXY || 'http://127.0.0.1:26001'; // 系统代理端口
const proxyAgent = new HttpsProxyAgent(proxyUrl);

// 添加错误处理中间件
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});

// 设置静态文件服务
app.use(express.static(__dirname));

// 添加CORS支持
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
next();
});

// 重试函数
async function fetchWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
console.log(`尝试连接 OpenAI API (第 ${i + 1} 次尝试)...`);
console.log('使用代理:', proxyUrl);
const response = await fetch(url, {
...options,
agent: proxyAgent,
timeout: 30000 // 30 秒超时
});
return response;
} catch (error) {
if (i === maxRetries - 1) throw error;
console.log(`尝试失败,等待重试... (${error.message})`);
await new Promise(resolve => setTimeout(resolve, 2000)); // 等待2秒后重试
}
}
}

// An endpoint which would work with the client code above - it returns
// the contents of a REST API request to this protected endpoint
app.get("/session", async (req, res) => {
try {
if (!process.env.OPENAI_API_KEY) {
throw new Error('OpenAI API key is not set');
}

console.log('使用的 API 密钥:', process.env.OPENAI_API_KEY.substring(0, 10) + '...');
console.log('尝试创建 OpenAI 会话...');

// 使用重试机制的 fetch
const r = await fetchWithRetry("https://api.openai.com/v1/realtime/sessions", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.OPENAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "gpt-4o-realtime-preview-2024-12-17",
voice: "verse",
}),
});

const responseText = await r.text();
console.log('OpenAI API 响应:', responseText);

if (!r.ok) {
throw new Error(`OpenAI API 返回 ${r.status}: ${responseText}`);
}

const data = JSON.parse(responseText);
console.log('会话创建成功');
res.json(data);
} catch (error) {
console.error('会话创建错误:', error);
res.status(500).json({
error: error.message,
details: error.stack
});
}
});

const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`服务器运行在端口 ${port}`);
console.log('OpenAI API 密钥:', process.env.OPENAI_API_KEY ? '已设置' : '未设置');
console.log('使用代理:', proxyUrl);
});
60 changes: 60 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<!DOCTYPE html>
<html>
<head>
<title>WebRTC OpenAI Demo</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
button {
padding: 10px 20px;
margin: 10px;
font-size: 16px;
}
#status {
margin: 20px 0;
padding: 10px;
border-radius: 5px;
}
#log {
background-color: #f5f5f5;
padding: 10px;
border-radius: 5px;
height: 200px;
overflow-y: auto;
margin-top: 20px;
}
</style>
</head>
<body>
<h1>WebRTC OpenAI Demo</h1>
<button id="connectButton" onclick="init()">开始连接</button>
<button id="disconnectButton" style="display: none;">断开连接</button>
<button id="sendButton" onclick="sendMessage()" disabled>发送测试消息</button>
<div id="status">状态:未连接</div>
<div id="log"></div>

<script>
// 重写console.log来显示在页面上
const oldLog = console.log;
console.log = function() {
const args = Array.from(arguments);
const message = args.map(arg =>
typeof arg === 'object' ? JSON.stringify(arg, null, 2) : arg
).join(' ');

const logDiv = document.getElementById('log');
if (logDiv) {
logDiv.innerHTML += message + '<br>';
logDiv.scrollTop = logDiv.scrollHeight;
}
oldLog.apply(console, arguments);
};
</script>
<script src="init.js"></script>
<script src="main.js"></script>
</body>
</html>
Loading

0 comments on commit c4b5c3b

Please sign in to comment.