Skip to content

Commit 9be9167

Browse files
authored
Merge branch 'develop' into e2e-tests
2 parents 8cb99c8 + 6f1d6e6 commit 9be9167

66 files changed

Lines changed: 3956 additions & 3416 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build-sfu.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ jobs:
2828
- name: Build and push Docker image
2929
uses: docker/build-push-action@v5
3030
with:
31-
context: ./sfu-server
31+
context: .
32+
file: ./sfu-server/Dockerfile
3233
push: true
3334
tags: ghcr.io/frappe/meet/sfu-server:latest

README.md

Lines changed: 30 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,110 +1,46 @@
1-
# Frappe Meet
1+
<div align="center">
22

3-
A video conferencing app built with Frappe.
3+
<a href="https://github.com/frappe/meet">
4+
<img src="https://frappe.io/files/meet_logo.png" height="80" alt="Frappe Meet Logo">
5+
</a>
46

5-
## Architecture
7+
<h1>Frappe Meet</h1>
68

7-
```
8-
┌─────────────┐ HTTP/WS ┌─────────────────────┐
9-
│ Client │ ◄─────────────► │ Frappe Server │
10-
│ (Frontend) │ │ (Auth, Perms etc) │
11-
│ │ └─────────────────────┘
12-
│ │
13-
│ │ Socket.IO (JWT Auth)
14-
│ │ ◄────────────────────────────────┐
15-
└─────────────┘ │
16-
17-
┌─────────────┐
18-
│ SFU Server │
19-
│ (mediasoup) │
20-
└─────────────┘
21-
```
9+
**Simple, High Quality Video Conferencing**
2210

23-
### Components
11+
</div>
2412

25-
1. **Client (Frontend)**: Vue.js application with WebRTC capabilities and direct SFU communication
26-
2. **Frappe Server**: Handles authentication, permissions, and meeting management
27-
3. **SFU Server (mediasoup)**: Handles transports, producers/consumers and media routing.
13+
> [!WARNING]
14+
> Frappe Meet is an alpha product and is not yet ready for production!
2815
29-
### Prerequisites
16+
## Frappe Meet
3017

31-
- Frappe Framework (v15+)
32-
- Node.js 18+ (recommended for mediasoup)
33-
- Python 3.10+
34-
- System deps for mediasoup (libc++, libsrtp, etc.)
18+
Frappe Meet is a video conferencing app built with simplicity, quality, and reliability in mind.
3519

36-
### 1. Install the Frappe App
20+
### Key Features
3721

38-
```bash
39-
cd $PATH_TO_YOUR_BENCH
40-
bench get-app $URL_OF_THIS_REPO --branch develop
41-
bench install-app meet
42-
```
22+
- **High-quality meetings:** Low-latency, scalable multi-party video with adaptive streaming.
23+
- **Meeting Management:** Create meetings and control meeting access for guests, participants, or hosts.
24+
- **Multimedia features:** Features like background effects, noise suppression, and push-to-talk elevate the meeting experience.
4325

44-
### 2. Setup SFU Server
26+
### Under the Hood
4527

46-
```bash
47-
# Navigate to SFU server directory
48-
cd apps/meet/sfu-server
28+
- [Mediasoup](https://github.com/versatica/mediasoup): Cutting Edge WebRTC Video Conferencing.
29+
- [Frappe Framework](https://github.com/frappe/frappe): A full-stack web application framework.
30+
- [Frappe UI](https://github.com/frappe/frappe-ui): A Vue-based UI library, to provide a modern user interface.
4931

50-
# Install dependencies (including new JWT support)
51-
npm install
52-
53-
cp .env.example .env
54-
# Minimum required settings in .env:
55-
# JWT_SECRET=your_jwt_secret_here
56-
# PORT=3000
57-
# HOST=0.0.0.0
58-
# WEBRTC_ANNOUNCED_IP=<public_ip_or_domain>
59-
60-
# Start SFU server
61-
npm start
62-
```
63-
64-
### 3. Configure Frappe Site
65-
66-
Add to your site config:
67-
68-
Add to `site_config.json` (values must match SFU):
69-
70-
```jsonc
71-
{
72-
"sfu_secret": "your_jwt_secret_here",
73-
"sfu_server_url": "https://your-domain.example"
74-
}
75-
```
76-
77-
### 4. Build Frontend
78-
79-
```bash
80-
cd apps/meet/frontend
81-
yarn install
82-
yarn build
83-
```
84-
85-
### Contributing
86-
87-
This app uses `pre-commit` for code formatting and linting. Please [install pre-commit](https://pre-commit.com/#installation) and enable it for this repository:
88-
89-
```bash
90-
cd apps/meet
91-
pre-commit install
92-
```
93-
94-
Pre-commit is configured to use the following tools for checking and formatting your code:
95-
96-
- ruff
97-
- eslint
98-
- prettier
99-
- pyupgrade
100-
101-
### CI
102-
103-
This app can use GitHub Actions for CI. The following workflows are configured:
104-
105-
- CI: Installs this app and runs unit tests on every push to `develop` branch.
106-
- Linters: Runs [Frappe Semgrep Rules](https://github.com/frappe/semgrep-rules) and [pip-audit](https://pypi.org/project/pip-audit/) on every pull request.
10732

10833
### License
10934

11035
AGPL-3.0
36+
37+
<br>
38+
<br>
39+
<div align="center">
40+
<a href="https://frappe.io" target="_blank">
41+
<picture>
42+
<source media="(prefers-color-scheme: dark)" srcset="https://frappe.io/files/Frappe-white.png">
43+
<img src="https://frappe.io/files/Frappe-black.png" alt="Frappe Technologies" height="28"/>
44+
</picture>
45+
</a>
46+
</div>

frontend/components.d.ts

Lines changed: 146 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -6,78 +6,150 @@
66
export {}
77

88
/* prettier-ignore */
9-
declare module 'vue' {
10-
export interface GlobalComponents {
11-
AudioIndicator: typeof import('./src/components/AudioIndicator.vue')['default']
12-
AudioSettingsTab: typeof import('./src/components/settings/AudioSettingsTab.vue')['default']
13-
BackgroundSettingsTab: typeof import('./src/components/settings/BackgroundSettingsTab.vue')['default']
14-
ChatNotification: typeof import('./src/components/ChatNotification.vue')['default']
15-
ChatNotificationQueue: typeof import('./src/components/ChatNotificationQueue.vue')['default']
16-
ChatPanel: typeof import('./src/components/ChatPanel.vue')['default']
17-
ClickToCopyField: typeof import('./src/components/ClickToCopyField.vue')['default']
18-
DeviceSettingsTab: typeof import('./src/components/settings/DeviceSettingsTab.vue')['default']
19-
EmojiPicker: typeof import('./src/components/EmojiPicker.vue')['default']
20-
FloatingControls: typeof import('./src/components/FloatingControls.vue')['default']
21-
FloatingReactions: typeof import('./src/components/FloatingReactions.vue')['default']
22-
GroupTile: typeof import('./src/components/GroupTile.vue')['default']
23-
JoinRequestNotifications: typeof import('./src/components/JoinRequestNotifications.vue')['default']
24-
KickParticipantDialog: typeof import('./src/components/KickParticipantDialog.vue')['default']
25-
LobbyOverlay: typeof import('./src/components/LobbyOverlay.vue')['default']
26-
LucideAlertCircle: typeof import('~icons/lucide/alert-circle')['default']
27-
LucideAlertTriangle: typeof import('~icons/lucide/alert-triangle')['default']
28-
LucideCheck: typeof import('~icons/lucide/check')['default']
29-
LucideCircleUserRound: typeof import('~icons/lucide/circle-user-round')['default']
30-
LucideClock: typeof import('~icons/lucide/clock')['default']
31-
LucideHand: typeof import('~icons/lucide/hand')['default']
32-
LucideHome: typeof import('~icons/lucide/home')['default']
33-
LucideLoader: typeof import('~icons/lucide/loader')['default']
34-
LucideMessageSquare: typeof import('~icons/lucide/message-square')['default']
35-
LucideMessageSquareDot: typeof import('~icons/lucide/message-square-dot')['default']
36-
LucideMessageSquareOff: typeof import('~icons/lucide/message-square-off')['default']
37-
LucideMic: typeof import('~icons/lucide/mic')['default']
38-
LucideMicOff: typeof import('~icons/lucide/mic-off')['default']
39-
LucideMonitorPause: typeof import('~icons/lucide/monitor-pause')['default']
40-
LucideMonitorUp: typeof import('~icons/lucide/monitor-up')['default']
41-
LucideMoreHorizontal: typeof import('~icons/lucide/more-horizontal')['default']
42-
LucideMoreVertical: typeof import('~icons/lucide/more-vertical')['default']
43-
LucidePhoneOff: typeof import('~icons/lucide/phone-off')['default']
44-
LucidePlay: typeof import("~icons/lucide/play")["default"]
45-
LucidePlayCircle: typeof import("~icons/lucide/play-circle")["default"]
46-
LucidePlus: typeof import('~icons/lucide/plus')['default']
47-
LucideSearch: typeof import('~icons/lucide/search')['default']
48-
LucideSettings: typeof import('~icons/lucide/settings')['default']
49-
LucideSmile: typeof import('~icons/lucide/smile')['default']
50-
LucideUserCheck: typeof import("~icons/lucide/user-check")["default"]
51-
LucideUserMinus: typeof import("~icons/lucide/user-minus")["default"]
52-
LucideUserPlus: typeof import("~icons/lucide/user-plus")["default"]
53-
LucideUsers: typeof import('~icons/lucide/users')['default']
54-
LucideVideo: typeof import('~icons/lucide/video')['default']
55-
LucideVideoOff: typeof import('~icons/lucide/video-off')['default']
56-
LucideWifiOff: typeof import('~icons/lucide/wifi-off')['default']
57-
LucideX: typeof import('~icons/lucide/x')['default']
58-
LucideXCircle: typeof import('~icons/lucide/x-circle')['default']
59-
MeetingAccessSettingsTab: typeof import('./src/components/settings/MeetingAccessSettingsTab.vue')['default']
60-
MeetingAvatar: typeof import('./src/components/MeetingAvatar.vue')['default']
61-
MeetingInfoDialog: typeof import('./src/components/MeetingInfoDialog.vue')['default']
62-
MeetingPreview: typeof import('./src/components/MeetingPreview.vue')['default']
63-
NamePill: typeof import('./src/components/NamePill.vue')['default']
64-
NotificationSettingsTab: typeof import('./src/components/settings/NotificationSettingsTab.vue')['default']
65-
ParticipantAvatarGroup: typeof import('./src/components/ParticipantAvatarGroup.vue')['default']
66-
ParticipantTile: typeof import('./src/components/ParticipantTile.vue')['default']
67-
PeoplePanel: typeof import('./src/components/PeoplePanel.vue')['default']
68-
PeopleParticipantTile: typeof import('./src/components/PeopleParticipantTile.vue')['default']
69-
PeopleWaitingSection: typeof import('./src/components/PeopleWaitingSection.vue')['default']
70-
ReactionPicker: typeof import('./src/components/ReactionPicker.vue')['default']
71-
RejectionOverlay: typeof import('./src/components/RejectionOverlay.vue')['default']
72-
RouterLink: typeof import('vue-router')['RouterLink']
73-
RouterView: typeof import('vue-router')['RouterView']
74-
ScreenShareLayout: typeof import('./src/components/ScreenShareLayout.vue')['default']
75-
ScreenShareSidebar: typeof import('./src/components/ScreenShareSidebar.vue')['default']
76-
ScreenShareSidebarParticipantTile: typeof import('./src/components/ScreenShareSidebarParticipantTile.vue')['default']
77-
SettingsDialog: typeof import('./src/components/settings/SettingsDialog.vue')['default']
78-
SettingsLayoutBase: typeof import('./src/components/settings/SettingsLayoutBase.vue')['default']
79-
SFUDashboard: typeof import('./src/components/SFUDashboard.vue')['default']
80-
VideoGrid: typeof import('./src/components/VideoGrid.vue')['default']
81-
VideoPreview: typeof import('./src/components/VideoPreview.vue')['default']
82-
}
9+
declare module "vue" {
10+
export interface GlobalComponents {
11+
AudioIndicator: typeof import(
12+
"./src/components/AudioIndicator.vue",
13+
)["default"];
14+
AudioSettingsTab: typeof import(
15+
"./src/components/settings/AudioSettingsTab.vue",
16+
)["default"];
17+
BackgroundSettingsTab: typeof import(
18+
"./src/components/settings/BackgroundSettingsTab.vue",
19+
)["default"];
20+
ChatNotification: typeof import(
21+
"./src/components/ChatNotification.vue",
22+
)["default"];
23+
ChatNotificationQueue: typeof import(
24+
"./src/components/ChatNotificationQueue.vue",
25+
)["default"];
26+
ChatPanel: typeof import("./src/components/ChatPanel.vue")["default"];
27+
ClickToCopyField: typeof import(
28+
"./src/components/ClickToCopyField.vue",
29+
)["default"];
30+
DeviceSettingsTab: typeof import(
31+
"./src/components/settings/DeviceSettingsTab.vue",
32+
)["default"];
33+
EmojiPicker: typeof import("./src/components/EmojiPicker.vue")["default"];
34+
FloatingReactions: typeof import(
35+
"./src/components/FloatingReactions.vue",
36+
)["default"];
37+
GroupTile: typeof import("./src/components/GroupTile.vue")["default"];
38+
JoinRequestNotifications: typeof import(
39+
"./src/components/JoinRequestNotifications.vue",
40+
)["default"];
41+
KickParticipantDialog: typeof import(
42+
"./src/components/KickParticipantDialog.vue",
43+
)["default"];
44+
LayoutSettingsTab: typeof import(
45+
"./src/components/settings/LayoutSettingsTab.vue",
46+
)["default"];
47+
LobbyOverlay: typeof import("./src/components/LobbyOverlay.vue")["default"];
48+
LucideAlertCircle: typeof import("~icons/lucide/alert-circle")["default"];
49+
LucideAlertTriangle: typeof import(
50+
"~icons/lucide/alert-triangle",
51+
)["default"];
52+
LucideCheck: typeof import("~icons/lucide/check")["default"];
53+
LucideCircleUserRound: typeof import(
54+
"~icons/lucide/circle-user-round",
55+
)["default"];
56+
LucideClock: typeof import("~icons/lucide/clock")["default"];
57+
LucideHand: typeof import("~icons/lucide/hand")["default"];
58+
LucideHome: typeof import("~icons/lucide/home")["default"];
59+
LucideLoader: typeof import("~icons/lucide/loader")["default"];
60+
LucideMessageSquare: typeof import(
61+
"~icons/lucide/message-square",
62+
)["default"];
63+
LucideMessageSquareDot: typeof import(
64+
"~icons/lucide/message-square-dot",
65+
)["default"];
66+
LucideMessageSquareOff: typeof import(
67+
"~icons/lucide/message-square-off",
68+
)["default"];
69+
LucideMic: typeof import("~icons/lucide/mic")["default"];
70+
LucideMicOff: typeof import("~icons/lucide/mic-off")["default"];
71+
LucideMonitorPause: typeof import("~icons/lucide/monitor-pause")["default"];
72+
LucideMonitorUp: typeof import("~icons/lucide/monitor-up")["default"];
73+
LucideMoreHorizontal: typeof import(
74+
"~icons/lucide/more-horizontal",
75+
)["default"];
76+
LucideMoreVertical: typeof import("~icons/lucide/more-vertical")["default"];
77+
LucidePhoneOff: typeof import("~icons/lucide/phone-off")["default"];
78+
LucidePlay: typeof import("~icons/lucide/play")["default"];
79+
LucidePlayCircle: typeof import("~icons/lucide/play-circle")["default"];
80+
LucidePlus: typeof import("~icons/lucide/plus")["default"];
81+
LucideSearch: typeof import("~icons/lucide/search")["default"];
82+
LucideSettings: typeof import("~icons/lucide/settings")["default"];
83+
LucideSmile: typeof import("~icons/lucide/smile")["default"];
84+
LucideUserCheck: typeof import("~icons/lucide/user-check")["default"];
85+
LucideUserMinus: typeof import("~icons/lucide/user-minus")["default"];
86+
LucideUserPlus: typeof import("~icons/lucide/user-plus")["default"];
87+
LucideUsers: typeof import("~icons/lucide/users")["default"];
88+
LucideVideo: typeof import("~icons/lucide/video")["default"];
89+
LucideVideoOff: typeof import("~icons/lucide/video-off")["default"];
90+
LucideX: typeof import("~icons/lucide/x")["default"];
91+
LucideXCircle: typeof import("~icons/lucide/x-circle")["default"];
92+
MeetingAccessSettingsTab: typeof import(
93+
"./src/components/settings/MeetingAccessSettingsTab.vue",
94+
)["default"];
95+
MeetingAvatar: typeof import(
96+
"./src/components/MeetingAvatar.vue",
97+
)["default"];
98+
MeetingInfoDialog: typeof import(
99+
"./src/components/MeetingInfoDialog.vue",
100+
)["default"];
101+
MeetingPreview: typeof import(
102+
"./src/components/MeetingPreview.vue",
103+
)["default"];
104+
MeetingToolbar: typeof import(
105+
"./src/components/MeetingToolbar.vue",
106+
)["default"];
107+
NamePill: typeof import("./src/components/NamePill.vue")["default"];
108+
NotificationSettingsTab: typeof import(
109+
"./src/components/settings/NotificationSettingsTab.vue",
110+
)["default"];
111+
ParticipantAvatarGroup: typeof import(
112+
"./src/components/ParticipantAvatarGroup.vue",
113+
)["default"];
114+
ParticipantTile: typeof import(
115+
"./src/components/ParticipantTile.vue",
116+
)["default"];
117+
PeoplePanel: typeof import("./src/components/PeoplePanel.vue")["default"];
118+
PeopleParticipantTile: typeof import(
119+
"./src/components/PeopleParticipantTile.vue",
120+
)["default"];
121+
PeopleWaitingSection: typeof import(
122+
"./src/components/PeopleWaitingSection.vue",
123+
)["default"];
124+
PreviewToolbar: typeof import(
125+
"./src/components/PreviewToolbar.vue",
126+
)["default"];
127+
ReactionPicker: typeof import(
128+
"./src/components/ReactionPicker.vue",
129+
)["default"];
130+
RejectionOverlay: typeof import(
131+
"./src/components/RejectionOverlay.vue",
132+
)["default"];
133+
RouterLink: typeof import("vue-router")["RouterLink"];
134+
RouterView: typeof import("vue-router")["RouterView"];
135+
ScreenShareLayout: typeof import(
136+
"./src/components/ScreenShareLayout.vue",
137+
)["default"];
138+
ScreenShareSidebar: typeof import(
139+
"./src/components/ScreenShareSidebar.vue",
140+
)["default"];
141+
ScreenShareSidebarParticipantTile: typeof import(
142+
"./src/components/ScreenShareSidebarParticipantTile.vue",
143+
)["default"];
144+
SettingsDialog: typeof import(
145+
"./src/components/settings/SettingsDialog.vue",
146+
)["default"];
147+
SettingsLayoutBase: typeof import(
148+
"./src/components/settings/SettingsLayoutBase.vue",
149+
)["default"];
150+
SFUDashboard: typeof import("./src/components/SFUDashboard.vue")["default"];
151+
Spinner: typeof import("./src/components/Spinner.vue")["default"];
152+
VideoGrid: typeof import("./src/components/VideoGrid.vue")["default"];
153+
VideoPreview: typeof import("./src/components/VideoPreview.vue")["default"];
154+
}
83155
}

0 commit comments

Comments
 (0)