├── .browserslistrc
├── .editorconfig
├── .eslintrc.js
├── .gitignore
├── README.md
├── babel.config.js
├── package.json
├── postcss.config.js
├── public
├── favicon.ico
└── index.html
├── src
├── App.vue
├── assets
│ └── img
│ │ └── bg.jpg
├── config.js
├── main.js
├── mixins
│ └── MeetMixin.js
├── router.js
└── views
│ ├── Join.vue
│ └── Meeting.vue
├── tests
└── e2e
│ ├── custom-assertions
│ └── elementCount.js
│ └── specs
│ └── test.js
└── vue.config.js
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not ie <= 8
4 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.{js,jsx,ts,tsx,vue}]
2 | indent_style = space
3 | indent_size = 2
4 | end_of_line = lf
5 | trim_trailing_whitespace = true
6 | insert_final_newline = true
7 | max_line_length = 100
8 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true,
5 | },
6 | extends: [
7 | 'plugin:vue/essential',
8 | '@vue/airbnb',
9 | ],
10 | rules: {
11 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
12 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
13 | },
14 | parserOptions: {
15 | parser: 'babel-eslint',
16 | },
17 | };
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 | package-lock.json
5 |
6 | /tests/e2e/reports/
7 | selenium-debug.log
8 |
9 | # local env files
10 | .env.local
11 | .env.*.local
12 |
13 | # Log files
14 | npm-debug.log*
15 | yarn-debug.log*
16 | yarn-error.log*
17 |
18 | # Editor directories and files
19 | .idea
20 | .vscode
21 | *.suo
22 | *.ntvs*
23 | *.njsproj
24 | *.sln
25 | *.sw*
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 重要提醒
2 | anyRTC 对该版本已经不再维护,如需音视频呼叫,请前往:https://github.com/anyRTC-UseCase/ARCall
3 |
4 | **功能如下:**
5 | - 一对一音视频呼叫
6 | - 一对多音视频呼叫
7 | - 视频通话转音频通话
8 | - 静音开关/视频开关
9 | - AI降噪,极致降噪,不留噪声
10 | - 大小屏切换
11 | - 悬浮窗功能
12 |
13 | 新版本一行代码,30分钟即可使应用有音视频能力。
14 |
15 | 更多示列请前往**公司网址: [www.anyrtc.io](https://www.anyrtc.io)**
16 |
17 | # anyRTC-Meeting-Web
18 |
19 | ## 使用
20 |
21 | ### Project setup
22 | ```
23 | npm install
24 | ```
25 |
26 | ### Compiles and hot-reloads for development
27 | ```
28 | npm run serve
29 | ```
30 |
31 | ### Compiles and minifies for production
32 | ```
33 | npm run build
34 | ```
35 |
36 | ## 更新日志
37 |
38 | 2019年5月14日:
39 |
40 | 使用最新的ar-meet 3.0 实时视频会议sdk
41 |
42 | ## 简介
43 | anyRTC-Meeting-Web SDK,支持视频、语音多人会议,适用于会议、培训、互动等多人移动会议。
44 |
45 | ## 集成
46 | 集成请参考[这里](https://docs.anyrtc.io/v1/MEET/web.html)
47 |
48 | ### 注册账号
49 |
50 | 登陆[AnyRTC官网](https://www.anyrtc.io/)
51 |
52 | ### 填写信息
53 |
54 | 创建应用,在管理中心获取开发者ID,AppID,AppKey,AppToken,替换AppDelegate.h中的相关信息
55 |
56 | ### 操作步骤:
57 |
58 | 打开[会议页面](https://demos.anyrtc.io/ar-meet/)进入同一个会议
59 |
60 | ### 资源中心
61 |
62 | [更多详细方法使用,请查看API文档](https://docs.anyrtc.io/v1/MEET/)
63 |
64 | ### 兼容情况
65 |
66 | - Chrome、Firefox、safari 11(以上)或其他谷歌内核浏览器
67 | - H5支持chrome内核
68 |
69 | ## 扫描二维码下载iOS demo
70 | 
71 |
72 | ## 扫描二维码下载Android demo
73 | 
74 |
75 | ## Android版anyRTC-Meeting
76 | [anyRTC-Meeting-Android](https://github.com/AnyRTC/anyRTC-meeting-Android)
77 |
78 | ## iOS版anyRTC-Meeting
79 | [anyRTC-Meeting-iOS](https://github.com/AnyRTC/anyRTC-meeting-iOS)
80 |
81 | ## 技术支持
82 | anyRTC官方网址:https://www.anyrtc.io
83 | anyRTC官方论坛:https://bbs.anyrtc.io
84 | QQ技术交流群:554714720
85 | 联系电话:021-65650071-816
86 | Email:hi@dync.cc
87 |
88 | ## 关于直播
89 | 本公司有一整套直播解决方案,特别针对移动端。本公司开发者平台[www.anyrtc.io](http://www.anyrtc.io)。除了基于RTMP协议的直播系统外,我公司还有基于WebRTC的时时交互直播系统、P2P呼叫系统、会议系统等。快捷集成SDK,便可让你的应用拥有时时通话功能。欢迎您的来电~
90 |
91 | ## License
92 |
93 | RTCMeetEngine is available under the MIT license. See the LICENSE file for more info.
94 |
95 | ### Customize configuration
96 | See [Configuration Reference](https://cli.vuejs.org/config/).
97 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/app',
4 | ],
5 | };
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ar-meet-demo",
3 | "version": "0.1.1",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "test:e2e": "vue-cli-service test:e2e"
9 | },
10 | "dependencies": {
11 | "vue": "^2.6.11",
12 | "vue-router": "^3.1.3"
13 | },
14 | "devDependencies": {
15 | "@vue/cli-plugin-babel": "^4.1.2",
16 | "@vue/cli-plugin-e2e-nightwatch": "^4.1.2",
17 | "@vue/cli-service": "^4.1.2",
18 | "ar-meet": "^3.0.17",
19 | "ar-share-screen": "3.0.1",
20 | "node-sass": "^4.13.0",
21 | "sass-loader": "^8.0.0",
22 | "vue-template-compiler": "^2.6.11"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {},
4 | },
5 | };
6 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anyrtcIO-Community/anyRTC-Meeting-Web/ae538b5bce0864fceb6374432240b9df9b478819/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | ar-meet
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
62 |
--------------------------------------------------------------------------------
/src/assets/img/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anyrtcIO-Community/anyRTC-Meeting-Web/ae538b5bce0864fceb6374432240b9df9b478819/src/assets/img/bg.jpg
--------------------------------------------------------------------------------
/src/config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | APP_ID: '',
3 | APP_TOKEN: '',
4 | RTC_SERVER_URL: '',//如果有部署私有云请配置私有云服务地址
5 | };
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import App from './App.vue';
3 | import router from './router';
4 |
5 | Vue.config.productionTip = false;
6 |
7 | new Vue({
8 | router,
9 | render: h => h(App),
10 | }).$mount('#app');
11 |
--------------------------------------------------------------------------------
/src/mixins/MeetMixin.js:
--------------------------------------------------------------------------------
1 | export default {
2 | data() {
3 | return {
4 |
5 | }
6 | },
7 |
8 | created() {
9 | if (JSON.stringify(this.$route.params) === "{}") {
10 | this.$router.push('/');
11 | } else {
12 | this.roomId = this.$route.params.roomId;
13 | this.isHoster = this.$route.params.isHoster || 0;
14 | }
15 | },
16 |
17 | mounted() {
18 | let that = this;
19 | that.handleResize();
20 | window.addEventListener('resize', that.handleResize, false);
21 | },
22 |
23 | methods: {
24 | handleResize(e) {
25 | let that = this;
26 | let videos = document.querySelectorAll('.ar-video_box');
27 | if (videos.length === 0) return;
28 | let videoArray = Array.prototype.slice.call(videos);
29 | let videoRect = that.$refs.videoView.getBoundingClientRect();
30 | let optimumWidth = 0;
31 | let optimumHeight = 0;
32 | let currentWidth = videoRect.width;
33 | let currentHeight = videoRect.height;
34 | //videoView最佳视图以当前的宽度计算
35 | if (parseInt(currentWidth * 9 / 16) < currentHeight) {
36 | optimumWidth = currentWidth;
37 | optimumHeight = parseInt(currentWidth * 9 / 16);
38 | }
39 | //最佳视图以当前的高度计算
40 | else {
41 | optimumWidth = parseInt(currentHeight * 16 / 9);
42 | optimumHeight = currentHeight;
43 | }
44 | that.$refs.videoWrap.style.width = optimumWidth + 'px';
45 | that.$refs.videoWrap.style.height = optimumHeight + 'px';
46 |
47 |
48 | if (videoArray.length > 1) {
49 | videoArray.map(item => {
50 | item.style.width = "50%";
51 | item.style.height = "50%";
52 | });
53 | }
54 | else {
55 | videos[0].style.width = optimumWidth + 'px';
56 | videos[0].style.height = optimumHeight + 'px';
57 | }
58 | }
59 | },
60 |
61 | destroyed() {
62 | window.removeEventListener('resize', this.handleResize, false);
63 | window.onbeforeunload = null;
64 | window.onunload = null;
65 | },
66 | }
--------------------------------------------------------------------------------
/src/router.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Router from 'vue-router';
3 | import Join from './views/Join.vue';
4 | import Meeting from './views/Meeting.vue';
5 |
6 | Vue.use(Router);
7 |
8 | export default new Router({
9 | mode: 'history',
10 | base: process.env.BASE_URL,
11 | routes: [
12 | {
13 | path: '/',
14 | name: 'Join',
15 | component: Join,
16 | },
17 | {
18 | // path: '/meet/:roomId/:isHoster',
19 | path: '/meet/:roomId',
20 | name: 'meeting',
21 | // route level code-splitting
22 | // this generates a separate chunk (about.[hash].js) for this route
23 | // which is lazy-loaded when the route is visited.
24 | component: Meeting,
25 | },
26 | ],
27 | });
28 |
--------------------------------------------------------------------------------
/src/views/Join.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
21 |
22 |
23 |
24 |
25 |
59 |
60 |
--------------------------------------------------------------------------------
/src/views/Meeting.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
11 |
12 | 视频源:
13 |
16 |
17 |
18 | 音频源:
19 |
22 |
23 |
27 |
31 |
32 |
日志
33 |
34 |
35 |
36 |
{{log.content}}
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 |
396 |
397 |
--------------------------------------------------------------------------------
/tests/e2e/custom-assertions/elementCount.js:
--------------------------------------------------------------------------------
1 | // A custom Nightwatch assertion.
2 | // The assertion name is the filename.
3 | // Example usage:
4 | //
5 | // browser.assert.elementCount(selector, count)
6 | //
7 | // For more information on custom assertions see:
8 | // http://nightwatchjs.org/guide#writing-custom-assertions
9 |
10 | exports.assertion = function elementCount(selector, count) {
11 | this.message = `Testing if element <${selector}> has count: ${count}`;
12 | this.expected = count;
13 | this.pass = val => val === count;
14 | this.value = res => res.value;
15 | function evaluator(_selector) {
16 | return document.querySelectorAll(_selector).length;
17 | }
18 | this.command = cb => this.api.execute(evaluator, [selector], cb);
19 | };
20 |
--------------------------------------------------------------------------------
/tests/e2e/specs/test.js:
--------------------------------------------------------------------------------
1 | // For authoring Nightwatch tests, see
2 | // http://nightwatchjs.org/guide#usage
3 |
4 | module.exports = {
5 | 'default e2e tests': (browser) => {
6 | browser
7 | .url(process.env.VUE_DEV_SERVER_URL)
8 | .waitForElementVisible('#app', 5000)
9 | .assert.elementPresent('.hello')
10 | .assert.containsText('h1', 'Welcome to Your Vue.js App')
11 | .assert.elementCount('img', 1)
12 | .end();
13 | },
14 | };
15 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | lintOnSave: false,
3 | publicPath: "/ar-meet/",
4 | devServer: {
5 | https: true
6 | }
7 | };
8 |
--------------------------------------------------------------------------------