张跃

初版

No preview for this file type
/scripts
\ No newline at end of file
module.exports = {
'env': {
'browser': true,
'es6': true,
'node': true,
'jquery': true,
},
'extends': 'eslint:recommended',
'globals': {
'Atomics': 'readonly',
'SharedArrayBuffer': 'readonly',
'AgoraRTC': 'readonly',
'AgoraRTS': 'readonly',
},
'parserOptions': {
'ecmaVersion': 2018,
'sourceType': 'module'
},
'rules': {
'indent': [
'warn',
2
],
'linebreak-style': [
'warn',
'unix'
],
'no-unused-vars': 0,
}
}
\ No newline at end of file
build
dist
package-lock.json
node_modules
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectDictionaryState">
<dictionary name="zhangyue" />
</component>
</project>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/Agora-Web-RTS-Tutorial-1to1-Webpack.iml" filepath="$PROJECT_DIR$/.idea/Agora-Web-RTS-Tutorial-1to1-Webpack.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
# Web Tutorial For Webpack - 1to1
*English | [中文](README.zh.md)*
This tutorial shows you how to quickly create an basic video communication using the Agora sample app.
## Prerequisites
- nodejs LTS
- A web browser
## Quick Start
This section shows you how to prepare, and run the sample application.
### Obtain an App ID
To build and run the sample application, get an App ID:
1. Create a developer account at [agora.io](https://dashboard.agora.io/signin/). Once you finish the signup process, you will be redirected to the Dashboard.
2. Navigate in the Dashboard tree on the left to **Projects** > **Project List**.
3. Save the **App ID** from the Dashboard for later use.
4. Generate a temp **Access Token** (valid for 24 hours) from dashboard page with given channel name, save for later use.
> To ensure communication security, Agora uses tokens (dynamic keys) to authenticate users joining a channel.
>
> Temporary tokens are for demonstration and testing purposes only and remain valid for 24 hours. In a production environment, you need to deploy your own server for generating tokens. See [Generate a Token](https://docs.agora.io/en/Interactive Broadcast/token_server)for details.
### Install dependencies and integrate the Agora Video SDK
1. Using the Terminal app, enter the `install` command in your project directory. This command installs libraries that are required to run the sample application.
``` bash
# install dependencies
npm install
```
2. Please download from [agora.io](https://docs.agora.io/en/) **AgoraRTC.js**, **AgoraRTS.js**, **AgoraRTS.asm**, **AgoraRTS.wasm** to `static` folder.
3. Start the application by entering the `run dev` or `run build` command.
The `run dev` command is for development purposes.
``` bash
# serve with hot reload at localhost:8080
npm run dev
```
The `run build` command is for production purposes and minifies code.
``` bash
# build for production with minification
npm run build
```
4. Your default browser should open and display the sample application, as shown here.
**Note:** In some cases, you may need to open a browser and enter `http://localhost:8080` as the URL.
## Contact Us
- For potential issues, take a look at our [FAQ](https://docs.agora.io/en/faq) first
- Dive into [Agora SDK Samples](https://github.com/AgoraIO) to see more tutorials
- Take a look at [Agora Use Case](https://github.com/AgoraIO-usecase) for more complicated real use case
- Repositories managed by developer communities can be found at [Agora Community](https://github.com/AgoraIO-Community)
- You can find full API documentation at [Document Center](https://docs.agora.io/en/)
- If you encounter problems during integration, you can ask question in [Stack Overflow](https://stackoverflow.com/questions/tagged/agora.io)
- You can file bugs about this sample at [issue](https://github.com/AgoraIO/Basic-Video-Call/issues)
## License
The MIT License (MIT)
Meta:
name: Web RTS Tutorial For Webpack - 1to1
lang: en
description: |
This tutorial shows you how to quickly create an basic video communication using the Agora sample app.
Prerequisites:
- nodejs LTS
- A web browser
QuickStart:
description:
This section shows you how to prepare, and run the sample application.
sections:
- title: Obtain an App ID
content: |
$_{APPID}
- title: Install dependencies and integrate the Agora Video SDK
content: |
1. Using the Terminal app, enter the `install` command in your project directory. This command installs libraries that are required to run the sample application.
``` bash
# install dependencies
npm install
```
2. Please download from [agora.io](https://docs.agora.io/en/) **AgoraRTC.js**, **AgoraRTS.js**, **AgoraRTS.asm**, **AgoraRTS.wasm** to `static` folder.
3. Start the application by entering the `run dev` or `run build` command.
The `run dev` command is for development purposes.
``` bash
# serve with hot reload at localhost:8080
npm run dev
```
The `run build` command is for production purposes and minifies code.
``` bash
# build for production with minification
npm run build
```
4. Your default browser should open and display the sample application, as shown here.
**Note:** In some cases, you may need to open a browser and enter `http://localhost:8080` as the URL.
Resources:
document: https://docs.agora.io/en/
issue: https://github.com/AgoraIO/Basic-Video-Call/issues
License:
type: MIT
\ No newline at end of file
# Web RTS Tutorial For Webpack - 1to1
*[English](README.md) | 中文*
这个开源示例项目演示了如何快速集成 Agora 视频 SDK,实现多人视频通话。
在这个示例项目中包含了以下功能:
- 加入通话和离开通话:
- 选择摄像头和麦克风设备:
## 环境准备
- nodejs LTS
- 浏览器
## 运行示例程序
This section shows you how to prepare, and run the sample application.
### 创建Agora账号并获取AppId
在编译和启动实例程序前,您需要首先获取一个可用的App ID:
1.[agora.io](https://dashboard.agora.io/signin/)创建一个开发者账号
2. 前往后台页面,点击左部导航栏的 **项目 > 项目列表** 菜单
3. 复制后台的 **App ID** 并备注,稍后启动应用时会用到它
4. 在项目页面生成临时 **Access Token** (24小时内有效)并备注,注意生成的Token只能适用于对应的频道名。
> 为提高项目的安全性,Agora 使用 Token(动态密钥)对即将加入频道的用户进行鉴权。
>
> 临时 Token 仅作为演示和测试用途。在生产环境中,你需要自行部署服务器签发 Token,详见[生成 Token](https://docs.agora.io/cn/Interactive Broadcast/token_server)。
### 集成 Agora 视频 SDK
1. 在Terminal中,在您的项目根目录输入`install`命令以安装项目依赖
```shell
# install dependencies
npm install
```
2. 请到官网[agora.io](https://docs.agora.io/cn/),下载这些文件 **AgoraRTC.js**, **AgoraRTS.js**, **AgoraRTS.asm**, **AgoraRTS.wasm**`static`目录。
3. 输入`run dev`命令以启动Web程序
```shell
# serve with hot reload at localhost:8080
npm run dev
```
输入`npm run build`会压缩静态资源文件,可作为生产环境打包发布。
``` bash
# build for production with minification
npm run build
```
4. 你的浏览器默认会打开示例应用程序。
**注意** 如果没有自动打开,请在浏览器里手动输入URL `http://localhost:8080`
## 联系我们
- 如果你遇到了困难,可以先参阅 [常见问题](https://docs.agora.io/cn/faq)
- 如果你想了解更多官方示例,可以参考 [官方SDK示例](https://github.com/AgoraIO)
- 如果你想了解声网SDK在复杂场景下的应用,可以参考 [官方场景案例](https://github.com/AgoraIO-usecase)
- 如果你想了解声网的一些社区开发者维护的项目,可以查看 [社区](https://github.com/AgoraIO-Community)
- 完整的 API 文档见 [文档中心](https://docs.agora.io/cn/)
- 若遇到问题需要开发者帮助,你可以到 [开发者社区](https://rtcdeveloper.com/) 提问
- 如果需要售后技术支持, 你可以在 [Agora Dashboard](https://dashboard.agora.io) 提交工单
- 如果发现了示例代码的 bug,欢迎提交 [issue](https://github.com/AgoraIO/Basic-Video-Call/issues)
## 代码许可
The MIT License (MIT)
Meta:
name: Web RTS Tutorial For Webpack - 1to1
lang: cn
description: |
这个开源示例项目演示了如何快速集成 Agora 视频 SDK,实现多人视频通话。
在这个示例项目中包含了以下功能:
- 加入通话和离开通话:
- 选择摄像头和麦克风设备:
Prerequisites:
- nodejs LTS
- 浏览器
QuickStart:
description:
This section shows you how to prepare, and run the sample application.
sections:
- title: 创建Agora账号并获取AppId
content: |
$_{APPID}
- title: 集成 Agora 视频 SDK
content: |
1. 在Terminal中,在您的项目根目录输入`install`命令以安装项目依赖
```shell
# install dependencies
npm install
```
2. 请到官网[agora.io](https://docs.agora.io/cn/),下载这些文件 **AgoraRTC.js**, **AgoraRTS.js**, **AgoraRTS.asm**, **AgoraRTS.wasm** 到`static`目录。
3. 输入`run dev`命令以启动Web程序
```shell
# serve with hot reload at localhost:8080
npm run dev
```
输入`npm run build`会压缩静态资源文件,可作为生产环境打包发布。
``` bash
# build for production with minification
npm run build
```
4. 你的浏览器默认会打开示例应用程序。
**注意** 如果没有自动打开,请在浏览器里手动输入URL `http://localhost:8080`。
Resources:
document: https://docs.agora.io/cn/
issue: https://github.com/AgoraIO/Basic-Video-Call/issues
License:
type: MIT
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>开放日</title>
</head>
<body class="agora-theme">
<script type="text/javascript" src="AgoraRTC.js"></script>
<script type="text/javascript" src="AgoraRTS.js"></script>
<div class="video-flex-container" id="video">
</div>
</body>
</html>
\ No newline at end of file
{
"name": "RTS-Tutorial",
"version": "2.9.0",
"description": "Agora-Web-RTS-Tutorial - One-to-One Video",
"keywords": [
"realtime-communication",
"agora-rtc-sdk",
"webrtc",
"agora-example",
"webpack",
"javascript"
],
"main": "index.js",
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --config ./scripts --mode development",
"build": "cross-env NODE_ENV=production webpack --config ./scripts --mode production",
"lint-fix": "eslint --fix src/ "
},
"dependencies": {
"axios": "^0.23.0",
"jquery": "^3.4.1",
"materialize-css": "^1.0.0",
"qrcode": "^1.4.1",
"sockjs-client": "^1.5.2",
"webstomp-client": "^1.2.6"
},
"devDependencies": {
"@babel/core": "^7.4.5",
"@babel/preset-env": "^7.4.5",
"babel-loader": "^8.0.6",
"clean-webpack-plugin": "^2.0.1",
"copy-webpack-plugin": "^5.0.4",
"cross-env": "^5.2.0",
"css-loader": "^2.1.1",
"ejs-render-loader": "^1.0.0",
"babel-eslint": "10.0.2",
"eslint": "^6.8.0",
"eslint-config-standard": "^14.1.1",
"eslint-loader": "^3.0.3",
"eslint-plugin-import": "^2.20.1",
"eslint-plugin-node": "^11.0.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"file-loader": "^3.0.1",
"friendly-errors-webpack-plugin": "^1.7.0",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.5.0",
"style-loader": "^0.23.1",
"webpack": "^4.29.6",
"webpack-cli": "^3.3.0",
"webpack-dev-server": "^3.2.1"
},
"author": "agora",
"license": "ISC"
}
const path = require("path");
const loaders = require("./loaders");
const plugins = require("./plugins");
const NODE_ENV = process.env.NODE_ENV
const distPath = NODE_ENV == 'development' ? '../dist' : '../build'
module.exports = {
entry: {
index: "./src/index.js",
},
devtool: "inline-source-map",
module: loaders,
plugins,
resolve: {
extensions: [ ".js", ".wasm" ],
},
output: {
filename: "[name].[hash].js",
path: path.resolve(__dirname, distPath),
},
optimization: {
minimize: false,
},
devServer: {
overlay: {
warnings: true,
errors: true,
},
hot: true,
contentBase: path.join(__dirname, "./"),
compress: true,
progress: true,
open: true,
proxy: {
'/openday-boot': {
target: 'https://openday.console.etoneiot.tech', // 请求本地 需要openday-boot后台项目
ws: true,
changeOrigin: true
}
}
},
};
const path = require("path");
const env = process.env;
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const styleLoader = env.NODE_ENV !== 'production' ? "style-loader" : MiniCssExtractPlugin.loader;
const babelLoader = {
test: /\.m?js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
};
const cssLoader = {
test: /\.css$/,
use: [
styleLoader,
"css-loader",
],
};
const eslintLoader = {
test: /\.js$/,
include: /src/,
use: {
loader: 'eslint-loader'
}
};
const fileLoader = {
test: /\.(png|svg|jpg|gif)$/,
use: "file-loader",
};
const fontLoader = {
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: "file-loader",
};
module.exports = {
rules: [
cssLoader,
fileLoader,
fontLoader,
babelLoader,
eslintLoader,
],
};
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const FriendlyErrorsPlugin = require("friendly-errors-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyPlugin = require('copy-webpack-plugin');
const path = require("path");
const resolve = path.resolve;
const webpack = require('webpack');
const NODE_ENV = process.env.NODE_ENV;
const copyPath = NODE_ENV == 'development' ? '../dist' : '../build';
const plugins = [
new HtmlWebpackPlugin({
filename: "index.html",
template: path.resolve(__dirname, "../index.html"),
}),
new CleanWebpackPlugin(),
new FriendlyErrorsPlugin({
compilationSuccessInfo: {
messages: ["You application is running here http://localhost:8080"],
notes: ["Some additionnal notes to be displayed upon successful compilation"],
},
onErrors: function(severity, errors) {},
clearConsole: true,
additionalFormatters: [],
additionalTransformers: [],
}),
new MiniCssExtractPlugin({
filename: "[name].[hash].css",
chunkFilename: "[id].css"
}),
new CopyPlugin([
{ from: resolve(__dirname, '../static'), to: resolve(__dirname, copyPath) },
]),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
Popper: 'popper.js/dist/umd/popper',
})
];
module.exports = plugins;
html, body,#video{
width: 100%;
height: 100%;
}
.video-view, .video-placeholder {
height: 100%;
}
\ No newline at end of file
export function addView (id) {
if (!$('#' + id)[0]) {
$('<div/>', {
id: 'remote_video_panel_' + id,
class: 'video-view',
}).appendTo('#video')
$('<div/>', {
id: 'remote_video_' + id,
class: 'video-placeholder',
}).appendTo('#remote_video_panel_' + id)
}
}
export function removeView (id) {
if ($('#remote_video_panel_' + id)[0]) {
$('#remote_video_panel_'+id).remove()
}
}
import RTCClient from './rtc-client';
import axios from "axios";
import stomp from "./stomp";
import './assets/style.css'
if (!AgoraRTS.checkSystemRequirements()) {
alert('Your web browser not support AgoraRTS!')
} else {
console.log('check success')
}
$(() => {
let rtc = new RTCClient()
let subscribes = [];
let sessionId = '';
let loading = false;
let token = '';
let noticeInfo = {};
function createWatch() {
subscribes = [];
subscribes.push({
topic: '/broadcast/live',
callback: (data) => {
if (data.body) {
let msg = JSON.parse(data.body)
if (msg.type === 'changeSid') {
sessionId = msg.content;
console.log(msg.content);
rtc.join(sessionId).then(() => {
console.log('加入')
})
}
if (msg.type === 'overLive') {
sessionId = '';
rtc.leave();
getNotice();
}
}
},
});
init();
}
function init() {
if (subscribes.length > 0) {
stomp.disconnect();
stomp.connect(subscribes);
}
}
createWatch();
axios.post('https://openday.console.etoneiot.tech/openday-boot/sys/mLogin', {
username: 'admin',
password: 'admin123'
}).then(r => {
if (r.data.code === 200) {
token = r.data.result.token;
getNotice();
}
})
function getNotice() {
axios.get('https://openday.console.etoneiot.tech/openday-boot/openday/notice', {
headers: {
'X-Access-Token': token
}
}).then(r => {
if (r.data.code === 200) {
noticeInfo = r.data.result;
sessionId = r.data.result.sessionId;
rtc.join(sessionId).then(() => {
console.log('加入')
})
} else {
noticeInfo = {};
sessionId = '';
}
})
}
})
\ No newline at end of file
import { addView, removeView} from './common'
console.log('agora sdk version: ' + AgoraRTC.VERSION + ' compatible: ' + AgoraRTC.checkSystemRequirements())
export default class RTCClient {
constructor () {
this._client = null
this._joined = false
this._published = false
this._localStream = null
this._remoteStreams = []
this._rtsStreamProfile = {}
this._params = {}
this._showProfile = false
}
handleEvents() {
this._client.on('error', (err) => {
console.log(err)
})
// Occurs when the peer user leaves the channel; for example, the peer user calls Client.leave.
this._client.on('peer-leave', (evt) => {
const id = evt.uid
if (id != this._params.uid) {
removeView(id)
}
// Toast.notice('peer leave')
console.log('peer-leave', id)
})
// Occurs when the remote stream is added.
this._client.on('stream-added', (evt) => {
const remoteStream = evt.stream
const id = remoteStream.getId()
// Toast.info('stream-added uid: ' + id)
if (id !== this._params.uid && remoteStream.hasVideo()) {
this._client.subscribe(remoteStream, (err) => {
console.log('stream subscribe failed', err)
})
}
console.log('stream-added remote-uid: ', id)
})
// Occurs when a user subscribes to a remote stream.
this._client.on('stream-subscribed', (evt) => {
const remoteStream = evt.stream
const id = remoteStream.getId()
this._remoteStreams.push(remoteStream)
addView(id)
remoteStream.play('remote_video_' + id, {fit: 'cover'})
// Toast.info('stream-subscribed remote-uid: ' + id)
console.log('stream-subscribed remote-uid: ', id)
})
// Occurs when the remote stream is removed; for example, a peer user calls Client.unpublish.
this._client.on('stream-removed', (evt) => {
const remoteStream = evt.stream
const id = remoteStream.getId()
// Toast.info('stream-removed uid: ' + id)
remoteStream.stop()
this._remoteStreams = this._remoteStreams.filter((stream) => {
return stream.getId() !== id
})
removeView(id)
console.log('stream-removed remote-uid: ', id)
})
}
join (sid) {
this.leave();
return new Promise((resolve, reject) => {
this._client = AgoraRTC.createClient({mode: 'live', codec: 'h264'})
AgoraRTS.init(AgoraRTC, {
wasmDecoderPath: 'AgoraRTS.wasm',
asmDecoderPath: 'AgoraRTS.asm',
bufferDelay: 3000,
maxBufferDelay: 10000,
}).catch(e => {
if (e === 'LOAD_DECODER_FAILED') {
console.log('Codec load failed!')
}
})
AgoraRTS.proxy(this._client)
this._params = {
sid
}
// handle AgoraRTC client event
this.handleEvents()
// init client
this._client.init('ac385634df8f4f62b4357ab35c54e88e', () => {
console.log('init success')
this._client.join(null, sid, null, (uid) => {
this._params.uid = uid
// Toast.notice('join channel: ' + sid + ' success, uid: ' + uid)
console.log('join channel: ' + sid + ' success, uid: ' + uid)
this._joined = true
// start stream interval stats
}, function(err) {
// Toast.error('client join failed, please open console see more detail')
console.error('client join failed', err)
})
}, (err) => {
// Toast.error('client init failed, please open console see more detail')
console.error(err)
})
})
}
leave () {
if (!this._client) {
// Toast.error('Please Join First!')
return
}
if (!this._joined) {
// Toast.error('You are not in channel')
return
}
// leave channel
this._client.leave(() => {
// stop stream
while (this._remoteStreams.length > 0) {
const stream = this._remoteStreams.shift()
const id = stream.getId()
stream.stop()
removeView(id)
}
this._localStream = null
this._remoteStreams = []
this._client = null
console.log('client leaves channel success')
this._published = false
this._joined = false
// Toast.notice('leave success')
}, (err) => {
console.log('channel leave failed')
// Toast.error('leave success')
console.error(err)
})
}
}
import SockJS from 'sockjs-client'
import Stomp from 'webstomp-client'
let stompClient = null
const getStompClient = function () {
if (stompClient === null) {
let socket = new SockJS('https://openday.console.etoneiot.tech/openday-boot/realtime')
stompClient = Stomp.over(socket)
stompClient.hasDebug = false
}
return stompClient
}
/**
* 连接服务
* @param [{ topic: String, callback: Function}]
*/
const connect = function (params) {
let client = getStompClient()
if (client.connected) {
return
}
let onConnected = function (frame) {
for (const param of params) {
if (!param.type) {
param.type = 'subscribe'
}
if (param.type === 'subscribe') {
client.subscribe(param.topic, param.callback)
}
if (param.type === 'send') {
if (!param.payload) {
param.payload = ""
}
client.send(param.topic, param.payload)
}
if (param.type === 'callback' && param.callback) {
param.callback(client)
}
}
}
client.connect({}, onConnected, (frame) => {
//自动重连
setTimeout(() => {
let socket = new SockJS('/openday-boot/realtime')
stompClient = Stomp.over(socket)
stompClient.hasDebug = false
connect(params)
}, 2000)
})
}
const disconnect = function () {
if (stompClient && stompClient.connected) {
stompClient.disconnect()
stompClient = null
}
}
const sendMessage = function (topic, message) {
if (stompClient && stompClient.connected) {
let msg = message
if (typeof msg !== 'string') {
msg = JSON.stringify(msg)
}
stompClient.send(topic, msg)
} else {
throw 'stomp client is null or disconnected'
}
}
export default {
connect,
disconnect,
sendMessage
}
No preview for this file type
File mode changed
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
No preview for this file type