Browse Source

播放地址拼接

release_0.0.2
巴林闲侠 3 years ago
parent
commit
517929e1ce
  1. 7
      code/VideoAccess-VCMP/api/.vscode/launch.json
  2. 2
      code/VideoAccess-VCMP/api/app/lib/controllers/camera/create.js
  3. 21
      code/VideoAccess-VCMP/api/app/lib/controllers/camera/index.js
  4. 29
      code/VideoAccess-VCMP/api/app/lib/schedule/freshYingshiMsg.js
  5. 22
      code/VideoAccess-VCMP/api/app/lib/utils/camera.js
  6. 39
      code/VideoAccess-VCMP/api/app/lib/utils/rtmp2others.js
  7. 80
      code/VideoAccess-VCMP/api/app/lib/utils/token4yingshi.js
  8. 35
      code/VideoAccess-VCMP/api/config.js

7
code/VideoAccess-VCMP/api/.vscode/launch.json

@ -23,7 +23,12 @@
"--iotVideoServerUrl http://221.230.55.27:8081",
"--godUrl https://restapi.amap.com/v3",
"--godKey 21c2d970e1646bb9a795900dd00093ce",
"--mqttVideoServer tcp://tee2b1be.cn.emqx.cloud:12847"
"--mqttVideoServer tcp://tee2b1be.cn.emqx.cloud:12847",
"--cameraPlayWsHost ws://221.230.55.27:8081",
"--cameraPlayHttpFlvHost http://221.230.55.27:2020",
"--cameraPlayHlsHost http://221.230.55.27:8081",
"--cameraPlayRtmpHost rtmp://221.230.55.27:1935",
"--cameraPlayRtspHost rtsp://221.230.55.27:554"
]
},
{

2
code/VideoAccess-VCMP/api/app/lib/controllers/camera/create.js

@ -361,7 +361,7 @@ async function getCascadeSipList (ctx) {
const { models } = ctx.fs.dc
const sipListRes = await models.GbCamera.findAll({
attributes: ['id', 'sipip'],
attributes: ['id', 'streamid', 'sipip'],
where: {
level: 0,
ipctype: '级联',

21
code/VideoAccess-VCMP/api/app/lib/controllers/camera/index.js

@ -7,6 +7,7 @@ async function getCameraProject (ctx, next) {
const models = ctx.fs.dc.models;
const { limit, page, orderBy, orderDirection, keyword, abilityId, type, venderId, nvrId, externalDomain, state } = ctx.query
const { userId, token } = ctx.fs.api
const { utils: { getPlayUrl } } = ctx.app.fs
let findOption = {
attributes: { exclude: ['delete', 'recycleTime',] },
@ -35,7 +36,7 @@ async function getCameraProject (ctx, next) {
}
let gbCameraOption = {
model: models.GbCamera,
attributes: ['id', 'online'],
attributes: ['id', 'online', 'playUrl'],
required: false
}
if (limit) {
@ -135,6 +136,10 @@ async function getCameraProject (ctx, next) {
camera.createUser = {
namePresent: corUser ? corUser.namePresent : ''
}
if (camera.type != 'yingshi') {
camera.gbCamera.dataValues.playUrl = getPlayUrl({ topSerialNo: camera.topSerialNo, serialNo: camera.serialNo })
}
}
ctx.status = 200;
@ -183,7 +188,7 @@ async function detail (ctx) {
const { models } = ctx.fs.dc;
const { cameraId } = ctx.params
const { userId, token } = ctx.fs.api
const { utils: { rtmp2others } } = ctx.app.fs
const { utils: { getPlayUrl } } = ctx.app.fs
const cameraRes = await models.Camera.findOne({
where: {
@ -208,19 +213,21 @@ async function detail (ctx) {
}
}
const otherUrls = await rtmp2others(cameraRes.rtmp)
const corUser = await ctx.app.fs.authRequest.get(`user/${cameraRes.createUserId}/message`, { query: { token } })
ctx.status = 200;
ctx.body = {
let rslt = {
...cameraRes.dataValues,
station: bindStations,
videoUrl: otherUrls,
createUser: {
namePresent: corUser[0].namePresent
}
}
if (cameraRes.type != 'yingshi') {
rslt.gbCamera.playUrl = await getPlayUrl({ topSerialNo: cameraRes.topSerialNo, serialNo: cameraRes.serialNo })
}
ctx.status = 200;
ctx.body = rslt
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;

29
code/VideoAccess-VCMP/api/app/lib/schedule/freshYingshiMsg.js

@ -9,7 +9,7 @@ module.exports = function (app, opts) {
try {
const startTime = moment()
const { models } = app.fs.dc
const { token4yingshi } = app.fs.utils
const { token4yingshi, getYingshiPlayUrl } = app.fs.utils
const secretRes = await models.SecretYingshi.findAll()
let deviceList = []
for (let s of secretRes) {
@ -44,6 +44,10 @@ module.exports = function (app, opts) {
if (existD) {
if (existD.online != storageD.online) {
// 状态更新
if (storageD.online == 'ON' && !existD.playUrl) {
const playUrlRes = await getYingshiPlayUrl({ deviceSerial: d.deviceSerial, token: tokenYingshi })
storageD.playUrl = playUrlRes
}
await models.GbCamera.update(storageD, {
where: {
id: existD.id
@ -112,15 +116,15 @@ module.exports = function (app, opts) {
});
const freshYingshiPlayUrl = schedule.scheduleJob(
// '* * 4 * * *',
'*/1 * * * *',
// '0 0 4 */1 *',
'*/45 * * * *',
async () => {
const protocolMap = {
}
try {
const { models } = app.fs.dc
const { token4yingshi } = app.fs.utils
const { token4yingshi, getYingshiPlayUrl } = app.fs.utils
const secretRes = await models.SecretYingshi.findAll()
for (let s of secretRes) {
const tokenYingshi = await token4yingshi(s.dataValues)
@ -135,23 +139,22 @@ module.exports = function (app, opts) {
}
})
if (deviceRes.code == 200) {
let deviceSerials = deviceRes.data.map(d => d.deviceSerial)
const devicePlayUrlRes = await app.fs.yingshiRequest.post('lapp/v2/live/address/get', {
query: {
accessToken: tokenYingshi,
deviceSerial: deviceSerials[0],
protocol: 3
for (let d of deviceRes.data) {
const playUrlRes = await getYingshiPlayUrl({ deviceSerial: d.deviceSerial, token: tokenYingshi })
await models.GbCamera.update({
playUrl: playUrlRes,
}, {
where: {
streamid: d.deviceSerial
}
})
}
if (deviceRes.data.length == 50) {
pageStart++
} else {
pageStart = -1
}
}
}
}

22
code/VideoAccess-VCMP/api/app/lib/utils/camera.js

@ -97,11 +97,33 @@ module.exports = function (app, opts) {
return gbCameraRes.dataValues
}
async function getPlayUrl ({ topSerialNo, serialNo }) {
const { cameraPlayHost } = opts
if (!topSerialNo || !serialNo) {
return null
}
return {
liveUrl: {
sd: {
'WS-RAW': `${cameraPlayHost.ws}/jessica/${topSerialNo}/${serialNo}`,
'WS-FLV': `${cameraPlayHost.ws}/jessica/${topSerialNo}/${serialNo}.flv`,
'HTTP-FLV': `${cameraPlayHost.httpFlv}/hdl/${topSerialNo}/${serialNo}.flv`,
'HLS': `${cameraPlayHost.httpFlv}/hls/${topSerialNo}/${serialNo}.m3u8`,
'RTMP': `${cameraPlayHost.rtmp}/${topSerialNo}/${serialNo}`,
'RTSP': `${cameraPlayHost.rtsp}/${topSerialNo}/${serialNo}`,
}
}
}
}
return {
getGbCameraLevel1ByStreamId,
getGbCameraLevel3ByStreamId,
verifyYingshiInfo,
verifyIpcInfo,
verifyCascadeInfo,
getPlayUrl,
}
}

39
code/VideoAccess-VCMP/api/app/lib/utils/rtmp2others.js

@ -1,39 +0,0 @@
'use strict';
module.exports = function (app, opts) {
async function rtmp2others (rtmp) {
return {
liveUrl: {// 直播
hd: {// 高清
rtmp: 'xx',
hls: 'xx',
flv: 'xx',
ezopen: 'xx',
onvif: 'xx',
},
sd: {// 标清
rtmp: 'xx',
hls: 'xx',
flv: 'xx',
ezopen: 'xx',
onvif: 'xx',
}
},
replayUrl: {// 回放
cloud: 'xx',
local: 'xx',
}
}
}
const getYingshiPlayUrl = async (deviceSerial) => {
}
return {
rtmp2others,
getYingshiPlayUrl,
}
}

80
code/VideoAccess-VCMP/api/app/lib/utils/token4yingshi.js

@ -68,8 +68,88 @@ module.exports = function (app, opts) {
return beloneSecret
}
const getYingshiPlayUrl = async ({ deviceSerial, token }) => {
const protocolMap = {
ezopen: 1,
hls: 2,
rtmp: 3,
flv: 4,
}
const qualityMap = {
hd: 1,
sd: 2,
}
const typeMap = {
// live: 1,
cloud: 2,
local: 3
}
let playUrl = {
liveUrl: {// 直播
hd: {// 高清
rtmp: '',
hls: '',
flv: '',
ezopen: '',
},
sd: {// 标清
rtmp: '',
hls: '',
flv: '',
ezopen: '',
}
},
replayUrl: {// 回放
cloud: '',
local: '',
}
}
for (let protocol in protocolMap) {
for (let quality in qualityMap) {
const playUrlRes = await app.fs.yingshiRequest.post('lapp/v2/live/address/get', {
query: {
accessToken: token,
deviceSerial: deviceSerial,
protocol: protocolMap[protocol],
quality: qualityMap[quality],
}
})
if (playUrlRes.code == 200) {
playUrl.liveUrl[quality][protocol] = playUrlRes.data.url
} else {
return null
}
}
}
for (let type in typeMap) {
try {
// TODO 这里404
const playUrlRes = await app.fs.yingshiRequest.post('lapp/v2/replay/address/get', {
query: {
accessToken: token,
deviceSerial: deviceSerial,
type: typeMap[type],
}
})
if (playUrlRes.code == 200) {
playUrl.replayUrl[type] = playUrlRes.data.url
} else {
// return null
}
} catch (error) {
app.fs.logger.error(`sechedule: freshYingshiPlayUrl, error: ${error}`);
}
}
return playUrl
}
return {
token4yingshi,
varifyYingshiBelongSecretBySerialNo,
getYingshiPlayUrl,
}
}

35
code/VideoAccess-VCMP/api/config.js

@ -11,15 +11,24 @@ const dev = process.env.NODE_ENV == 'development';
args.option(['p', 'port'], '启动端口');
args.option(['g', 'pg'], 'postgre服务URL');
args.option(['f', 'fileHost'], '文件中心本地化存储: WebApi 服务器地址(必填), 该服务器提供文件上传Web服务');
args.option('redisHost', 'redisHost');
args.option('redisPort', 'redisPort');
args.option('redisPswd', 'redisPassword');
args.option('axyApiUrl', '安心云 api');
args.option('iotAuthApi', 'IOT 鉴权 api');
args.option('iotVideoServerUrl', '视频后端服务地址');
args.option('godUrl', '高德地图API请求地址');
args.option('godKey', '高德地图API key');
args.option('iotVideoServerUrl', '视频后端服务地址');
args.option('mqttVideoServer', '视频后台 mqtt 服务 URL');
args.option('cameraPlayWsHost', '视频播放地址 ws://xxx:xxx');
args.option('cameraPlayHttpFlvHost', '视频播放地址 httpFlv');
args.option('cameraPlayHlsHost', '视频播放地址 hls');
args.option('cameraPlayRtmpHost', '视频播放地址 rtmp');
args.option('cameraPlayRtspHost', '视频播放地址 rtsp');
const flags = args.parse(process.argv);
@ -30,17 +39,26 @@ const IOTA_REDIS_SERVER_HOST = process.env.IOTA_REDIS_SERVER_HOST || flags.redis
const IOTA_REDIS_SERVER_PORT = process.env.IOTA_REDIS_SERVER_PORT || flags.redisPort || "6379";//redis 端口
const IOTA_REDIS_SERVER_PWD = process.env.IOTA_REDIS_SERVER_PWD || flags.redisPswd || "";//redis 密码
const MQTT_VIDEO_SERVER = process.env.MQTT_VIDEO_SERVER || flags.mqttVideoServer;
const IOT_AUTH_API = process.env.IOT_AUTH_API || flags.iotAuthApi;
const IOT_VIDEO_SERVER_URL = process.env.IOT_VIDEO_SERVER_URL || flags.iotVideoServerUrl
const AXY_API_URL = process.env.AXY_API_URL || flags.axyApiUrl;
const GOD_URL = process.env.GOD_URL || flags.godUrl || 'https://restapi.amap.com/v3';
const GOD_KEY = process.env.GOD_KEY || flags.godKey;
const YINGSHI_URL = process.env.YINGSHI_URL || flags.yingshiUrl || 'https://open.ys7.com/api';
const MQTT_VIDEO_SERVER = process.env.MQTT_VIDEO_SERVER || flags.mqttVideoServer;
const IOT_VIDEO_SERVER_URL = process.env.IOT_VIDEO_SERVER_URL || flags.iotVideoServerUrl
const CAMERA_PLAY_WS_HOST = process.env.CAMERA_PLAY_WS_HOST || flags.cameraPlayWsHost;
const CAMERA_PLAY_HTTP_FLV_HOST = process.env.CAMERA_PLAY_HTTP_FLV_HOST || flags.cameraPlayHttpFlvHost;
const CAMERA_PLAY_HLS_HOST = process.env.CAMERA_PLAY_HLS_HOST || flags.cameraPlayHlsHost;
const CAMERA_PLAY_RTMP_HOST = process.env.CAMERA_PLAY_RTMP_HOST || flags.cameraPlayRtmpHost;
const CAMERA_PLAY_RTSP_HOST = process.env.CAMERA_PLAY_RTSP_HOST || flags.cameraPlayRtspHost;
if (!IOT_VIDEO_ACCESS_DB || !IOTA_REDIS_SERVER_HOST || !IOTA_REDIS_SERVER_PORT || !GOD_KEY || !MQTT_VIDEO_SERVER ||
!AXY_API_URL || !IOT_VIDEO_SERVER_URL || !IOT_AUTH_API) {
!AXY_API_URL || !IOT_VIDEO_SERVER_URL || !IOT_AUTH_API ||
!CAMERA_PLAY_WS_HOST || !CAMERA_PLAY_HTTP_FLV_HOST || !CAMERA_PLAY_HLS_HOST || !CAMERA_PLAY_RTMP_HOST || !CAMERA_PLAY_RTSP_HOST
) {
console.log('缺少启动参数,异常退出');
args.showHelp();
process.exit(-1);
@ -72,6 +90,13 @@ const product = {
mqtt: {
mqttVideoServer: MQTT_VIDEO_SERVER,
},
cameraPlayHost: {
ws: CAMERA_PLAY_WS_HOST,
httpFlv: CAMERA_PLAY_HTTP_FLV_HOST,
hls: CAMERA_PLAY_HLS_HOST,
rtmp: CAMERA_PLAY_RTMP_HOST,
rtsp: CAMERA_PLAY_RTSP_HOST,
},
pssaRequest: [
{// name 会作为一个 request 出现在 ctx.app.fs
name: 'authRequest',

Loading…
Cancel
Save