1 Star 0 Fork 9

w3ipc/zlm_webassist

forked from 1002victor/zlm_webassist 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
index.html 172.98 KB
一键复制 编辑 原始数据 按行查看 历史
mtdxc 提交于 2024-11-04 02:35 . 微调显示样式 (#8)
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="icon" type="image/x-icon" href="./assets/favicon.ico">
<!-- import CSS -->
<link rel="stylesheet" href="./assets/elementui/index.css">
<!-- import JS -->
<script src="./js/utils.js"></script>
</head>
<body>
<div id="app">
<el-container>
<el-header>
<el-row>
<el-col :xs="23" :sm="23" :md="23" :lg="23" :xl="23">
<el-menu :default-active="selectIndex" class="el-menu-demo" mode="horizontal"
@select="handleSelect" background-color="#545c64" text-color="#fff"
active-text-color="#ffd04b">
<el-menu-item index="1" disable> <template slot="title">
<el-image style="height: 100%" src="./assets/logo.png" fit="fill"></el-image>
</template>
</el-menu-item>
<el-menu-item index="2">WebRTC测试</el-menu-item>
<el-menu-item index="3">拉流代理</el-menu-item>
<el-menu-item index="4">推流代理</el-menu-item>
<el-menu-item index="5">FFmpeg推拉流</el-menu-item>
<el-menu-item index="6">Rtp服务</el-menu-item>
<el-menu-item index="7">服务器配置</el-menu-item>
</el-menu>
</el-col>
<el-col :xs="1" :sm="1" :md="1" :lg="1" :xl="1" v-show="selectIndex==='7'">
<el-popconfirm confirm-button-text='好的' cancel-button-text='不用了' icon="el-icon-info"
icon-color="red" title="这只有Daemon方式才能重启,否则是直接关闭!确定重启吗?" @confirm="restartServer">
<el-button type="danger" plain slot="reference" icon="el-icon-refresh-right">重启</el-button>
</el-popconfirm>
</el-col>
</el-row>
</el-header>
<el-main>
<div v-show="selectIndex==='1'">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
<div style="height: 300px; background-color: whitesmoke; border-radius: 20px;">
<div style="height: 100%; width: 100%;" ref="chart1">
</div>
</div>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
<div style="height: 300px; background-color: whitesmoke; border-radius: 20px;">
<div style="height: 100%; width: 100%;" ref="chart2">
</div>
</div>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
<div style="height: 300px; background-color: whitesmoke;border-radius: 20px;">
<div style="height: 100%; width: 100%;" ref="chart3">
</div>
</div>
</el-col>
</el-row>
<el-divider><i class="el-icon-s-data"></i></el-divider>
<div style="width: 100%;text-align: right;">
<el-checkbox label="自动刷新" v-model="autorefresh_medialist" ></el-checkbox>
<el-button type="primary" icon="el-icon-refresh" @click="getMediaList">刷新</el-button>
</div>
<el-table :data="medialist" empty-text="暂无数据">
<!-- <el-table-column prop="vhost" label="主机名"> </el-table-column> -->
<el-table-column sortable prop="app" label="应用名"> </el-table-column>
<el-table-column prop="stream" label="流id"> </el-table-column>
<el-table-column sortable prop="schema" label="协议" :filters="schemaFilters" :filter-method="filterSchema"> </el-table-column>
<el-table-column prop="createStamp" label="创建时间">
<template #default="scope">
{{scope.row.createStamp | secFormat}}
</template>
</el-table-column>
<el-table-column prop="aliveSecond" label="时长(s)">
</el-table-column>
<el-table-column prop="bytesSpeed" label="码率">
<template #default="scope">
{{scope.row.bytesSpeed | bitsSpeed}}/s
</template>
</el-table-column>
<el-table-column label="录制">
<template #default="scope">
<el-tag v-if="scope.row.isRecordingHLS">录制HLS</el-tag>
<el-tag v-if="scope.row.isRecordingMP4">录制Mp4</el-tag>
</template>
</el-table-column>
<!--
<el-table-column prop="isRecordingHLS" label="是否录制HLS">
<template #default="scope">
<el-tag v-if="scope.row.isRecordingHLS" type="success" effect="dark">是</el-tag>
<el-tag v-else type="danger" effect="dark">否</el-tag>
</template>
</el-table-column>
<el-table-column prop="isRecordingMP4" label="是否录制MP4">
<template #default="scope">
<el-tag v-if="scope.row.isRecordingMP4" type="success" effect="dark">是</el-tag>
<el-tag v-else type="danger" effect="dark">否</el-tag>
</template>
</el-table-column>
<el-table-column prop="originType" label="源类型">
<template #default="scope">
<el-tag v-if="scope.row.originType==0">unknown</el-tag>
<el-tag v-else-if="scope.row.originType==1">rtmp_push</el-tag>
<el-tag v-else-if="scope.row.originType==2">rtsp_push</el-tag>
<el-tag v-else-if="scope.row.originType==3">rtp_push</el-tag>
<el-tag v-else-if="scope.row.originType==4">pull</el-tag>
<el-tag v-else-if="scope.row.originType==5">ffmpeg_pull</el-tag>
<el-tag v-else-if="scope.row.originType==6">mp4_vod</el-tag>
<el-tag v-else-if="scope.row.originType==7">device_chn</el-tag>
<el-tag v-else-if="scope.row.originType==8">rtc_push</el-tag>
</template>
</el-table-column>
-->
<el-table-column prop="originTypeStr" label="类型"> </el-table-column>
<el-table-column prop="originUrl" label="源地址"> </el-table-column>
<!--
<el-table-column prop="readerCount" label="本协议观看人数"> </el-table-column>
<el-table-column sortable prop="totalReaderCount" label="观看总人数"> </el-table-column>
-->
<el-table-column sortable prop="totalReaderCount" label="观看人数">
<template slot-scope="scope">
<el-button @click="getPlayerList(scope.row)">{{scope.row.readerCount}}/{{scope.row.totalReaderCount}}</el-button>
</template>
</el-table-column>
<el-table-column label="网络信息">
<el-table-column prop="originSock.identifier" label="identifier"> </el-table-column>
<el-table-column label="local_ip">
<template slot-scope="scope">{{scope.row.originSock.local_ip}}:{{scope.row.originSock.local_port}}</template>
</el-table-column>
<el-table-column label="peer_ip">
<template slot-scope="scope">{{scope.row.originSock.peer_ip}}:{{scope.row.originSock.peer_port}}</template>
</el-table-column>
<!--
<el-table-column prop="originSock.local_ip" label="local_ip"> </el-table-column>
<el-table-column prop="originSock.local_port" label="local_port"> </el-table-column>
<el-table-column prop="originSock.peer_ip" label="peer_ip"> </el-table-column>
<el-table-column prop="originSock.peer_port" label="peer_port"> </el-table-column>
-->
</el-table-column>
<el-table-column type="expand" label="媒体轨道">
<template slot-scope="scope">
<el-table v-if="scope.row.tracks.length > 0" :data="scope.row.tracks">
<!--
<el-table-column prop="codec_type" label="编码类型">
</el-table-column>
<el-table-column prop="codec_id" label="编码类型ID">
</el-table-column>
-->
<el-table-column prop="codec_id_name" label="编码">
<template #default="scope">
<el-tag type="success">{{ scope.row.codec_id_name}}</el-tag>
</template>
</el-table-column>
<el-table-column prop="frames" label="接收帧数">
</el-table-column>
<el-table-column prop="duration" label="时长(s)">
<template #default="scope">{{ scope.row.duration/1000}}</template>
</el-table-column>
<el-table-column prop="ready" label="已就绪">
<template #default="scope">
<el-tag v-if="scope.row.ready" type="success" effect="dark"></el-tag>
<el-tag v-else type="danger" effect="dark"></el-tag>
</template>
</el-table-column>
<el-table-column label="编码属性">
<template #default="scope">
<el-tag v-if="scope.row.codec_type==1">{{scope.row.channels}}x{{scope.row.sample_rate}}x{{scope.row.sample_bit}}</el-tag>
<el-tag v-else>{{scope.row.width}}x{{scope.row.height}}@{{scope.row.fps}}</el-tag>
</template>
</el-table-column>
<el-table-column prop="key_frames" label="关键帧数">
</el-table-column>
<el-table-column prop="gop_interval_ms" label="gop间隔时间(s)">
</el-table-column>
<el-table-column prop="gop_size" label="gop大小">
</el-table-column>
</el-table>
<el-empty description="无tracks" v-else></el-empty>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button size="mini" type="danger"
@click="close_stream(scope.$index, scope.row)">关闭</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog :title="playerTitle"
width="60%" top="2rem"
:close-on-click-modal="true"
:visible.sync="showPlayerDialog">
<div id="shared" style="margin-top: 1rem;">
<el-table :data="playerlist" empty-text="暂无播放器">
<el-table-column prop="identifier" label="id"></el-table-column>
<el-table-column prop="local_ip" label="本机ip"></el-table-column>
<el-table-column prop="local_port" label="本机端口"></el-table-column>
<el-table-column prop="peer_ip" label="对端ip"></el-table-column>
<el-table-column prop="peer_port" label="对端端口"></el-table-column>
<el-table-column prop="typeid" label="类型"></el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button size="mini" type="danger"
@click="kick_session(scope.row.identifier)">断开</el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-dialog>
<el-divider><i class="el-icon-connection"></i></el-divider>
<div style="width: 100%;text-align: right;">
<el-checkbox label="自动刷新" v-model="autorefresh_session" ></el-checkbox>
<el-button type="primary" icon="el-icon-refresh" @click="getAllSession">刷新</el-button>
</div>
<el-table :data="sessionlist" empty-text="暂无连接数据">
<el-table-column prop="id" label="id"></el-table-column>
<el-table-column prop="local_ip" label="本机ip"></el-table-column>
<el-table-column prop="local_port" label="本机端口"></el-table-column>
<el-table-column prop="peer_ip" label="对端ip"></el-table-column>
<el-table-column prop="peer_port" label="对端端口"></el-table-column>
<el-table-column prop="typeid" label="类型"></el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button size="mini" type="danger"
@click="kick_session(scope.row.id)">断开</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div v-show="selectIndex==='2'">
<el-row :gutter="20">
<el-col :span="24">
<el-row :gutter="10" style="height: 600px;display: flex; margin-bottom: 10px;">
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<video ref='video' controls autoplay class="videobox">
Your browser is too old which doesn't support HTML5 video.
</video>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<video ref='selfVideo' controls autoplay class="videobox">
Your browser is too old which doesn't support HTML5 video.
</video>
</el-col>
</el-row>
</el-col>
<el-col :span="12" :offset="6">
<el-form v-model="webrtc" label-width="160px">
<el-form-item label="url">
<el-input v-model="webrtc.zlmsdpUrl"></el-input>
</el-form-item>
<el-form-item label="">
<el-checkbox label="simulcast" v-model="webrtc.simulcast"></el-checkbox>
<el-checkbox label="useCamera" v-model="webrtc.useCamera"></el-checkbox>
<el-checkbox label="audioEnable" v-model="webrtc.audioEnable"></el-checkbox>
<el-checkbox label="videoEnable" v-model="webrtc.videoEnable"></el-checkbox>
</el-form-item>
<el-form-item label="method">
<el-radio-group v-model="webrtc.type">
<el-radio label="echo"></el-radio>
<el-radio label="push"></el-radio>
<el-radio label="play"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="resolution">
<el-select v-model="webrtc.resolution" placeholder="请选择分辨率" @change="$forceUpdate()"
style="width: 100%;">
<el-option v-for="(opt,index) in resolution_opt" :key="index" :label="opt.text"
:value="index"></el-option>
</el-select>
</el-form-item>
<el-form-item label="datachannel">
<el-switch v-model="webrtc.usedatachannel"></el-switch>
</el-form-item>
<el-form-item label="debug日志">
<el-switch v-model="webrtc.debug"></el-switch>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="startwebrtc">开始(start)</el-button>
<el-button type="danger" @click="stopwebrtc">停止(stop)</el-button>
</el-form-item>
<el-form-item label="msgrecv">
<el-input type="textarea" v-model="webrtc.msgrecv"></el-input>
</el-form-item>
<el-form-item label="msgsend">
<el-input type="text" v-model="webrtc.msgsend">
<template slot="append">
<el-button type="success" @click="sendata">发送数据</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item>
<el-button type="info" @click="closedata">关闭(close datachannel)</el-button>
</el-form-item>
</el-form>
</el-col>
</el-row>
</div>
<div v-if="selectIndex==='3'" style="display: flex;">
<div style="border-radius: 4px; background-color: #545c6421;margin: 10px; flex:1">
<el-form style="margin: 10px;">
<!-- <el-form-item label="api操作密钥" label-width="180px">
<el-input v-model="secret" disabled></el-input>
</el-form-item> -->
<el-form-item label="虚拟主机" label-width="180px">
<el-input v-model="addStreamProxy_params.vhost"></el-input>
</el-form-item>
<el-form-item label="应用名" label-width="180px">
<el-input v-model="addStreamProxy_params.app"></el-input>
</el-form-item>
<el-form-item label="流id" label-width="180px">
<el-input v-model="addStreamProxy_params.stream"></el-input>
</el-form-item>
<el-form-item label="拉流地址" label-width="180px">
<el-input v-model="addStreamProxy_params.url"
placeholder="例如rtmp://live.hkstv.hk.lxdns.com/live/hks2"></el-input>
</el-form-item>
<el-form-item label="" label-width="180px">
<el-row style="text-align: left;">
<el-col :span="8">
<el-checkbox
v-model="addStreamProxy_params.enable_hls">转hls-mpeg</el-checkbox>
</el-col>
<el-col :span="8">
<el-checkbox
v-model="addStreamProxy_params.enable_hls_fmp4">转hls-fmp4</el-checkbox>
</el-col>
<el-col :span="8">
<el-checkbox
v-model="addStreamProxy_params.enable_mp4">mp4录制</el-checkbox>
</el-col>
<el-col :span="8">
<el-checkbox
v-model="addStreamProxy_params.enable_rtsp">转rtsp</el-checkbox>
</el-col>
<el-col :span="8">
<el-checkbox
v-model="addStreamProxy_params.enable_rtmp">转rtmp/flv</el-checkbox>
</el-col>
<el-col :span="8">
<el-checkbox
v-model="addStreamProxy_params.enable_ts">转http-ts/ws-ts</el-checkbox>
</el-col>
<el-col :span="8">
<el-checkbox
v-model="addStreamProxy_params.enable_fmp4">转http-fmp4/ws-fmp4</el-checkbox>
</el-col>
<el-col :span="8">
<el-checkbox
v-model="addStreamProxy_params.hls_demand">按需生成hls</el-checkbox>
</el-col>
<el-col :span="8">
<el-checkbox
v-model="addStreamProxy_params.rtsp_demand">按需生成rtsp</el-checkbox>
</el-col>
<el-col :span="8">
<el-checkbox
v-model="addStreamProxy_params.rtmp_demand">按需生成rtmp</el-checkbox>
</el-col>
<el-col :span="8">
<el-checkbox
v-model="addStreamProxy_params.ts_demand">按需生成ts</el-checkbox>
</el-col>
<el-col :span="8">
<el-checkbox
v-model="addStreamProxy_params.fmp4_demand">按需生成fmp4</el-checkbox>
</el-col>
<el-col :span="8">
<el-checkbox
v-model="addStreamProxy_params.enable_audio">允许音频</el-checkbox>
</el-col>
<el-col :span="8">
<el-checkbox
v-model="addStreamProxy_params.add_mute_audio">添加静音音轨</el-checkbox>
</el-col>
<el-col :span="16">
<el-checkbox
v-model="addStreamProxy_params.mp4_as_player">MP4录制当作观看者参与播放人数计数</el-checkbox>
</el-col>
<el-col :span="16">
<el-checkbox
v-model="addStreamProxy_params.auto_close">无人观看自动关闭流(不触发无人观看hook)</el-checkbox>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="拉流方式" label-width="180px">
<el-select v-model="addStreamProxy_params.rtp_type" style="width: 100%;">
<el-option label="TCP" value="0"> </el-option>
<el-option label="UDP" value="1"> </el-option>
<el-option label="组播" value="2"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="超时时间" label-width="180px">
<el-input v-model="addStreamProxy_params.timeout_sec"></el-input>
</el-form-item>
<el-form-item label="重试次数" label-width="180px">
<el-input v-model="addStreamProxy_params.retry_count" placeholder="默认为-1无限重试"></el-input>
</el-form-item>
<el-form-item label="时间戳覆盖" label-width="180px">
<el-select v-model="addStreamProxy_params.modify_stamp" style="width: 100%;">
<el-option label="不开启" value=""> </el-option>
<el-option label="绝对时间戳" value="0"> </el-option>
<el-option label="系统时间戳" value="1"> </el-option>
<el-option label="相对时间戳" value="2"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="mp4录像保存目录" label-width="180px">
<el-input v-model="addStreamProxy_params.mp4_save_path"
placeholder="mp4录像保存目录,置空使用默认"></el-input>
</el-form-item>
<el-form-item label="mp4切片大小(s)" label-width="180px">
<el-input v-model="addStreamProxy_params.mp4_max_second"
placeholder="mp4录像切片大小(s)"></el-input>
</el-form-item>
<el-form-item label="hls文件保存目录" label-width="180px">
<el-input v-model="addStreamProxy_params.hls_save_path"
placeholder="hls文件保存目录,置空使用默认"></el-input>
</el-form-item>
<el-form-item label="">
<el-input type="textarea" :rows="5" v-model="apiurl" readonly></el-input>
</el-form-item>
</el-form>
</div>
<div style="border-radius: 4px; background-color: #545c6421;margin: 10px; flex:1">
<el-form style="margin: 10px;">
<div style="margin-bottom: 10px;width: 100%;text-align: left;">
<el-button type="primary" @click="addStreamProxy">增加</el-button>
<el-button type="primary" icon="el-icon-refresh" @click="listStreamProxy">刷新</el-button>
</div>
<el-table :data="streamProxyList" empty-text="暂无拉流代理">
<!-- <el-table-column sortable prop="key" label="key"> </el-table-column> -->
<el-table-column sortable prop="url" label="url"> </el-table-column>
<el-table-column sortable prop="src.app" label="app"> </el-table-column>
<el-table-column sortable prop="src.stream" label="stream"> </el-table-column>
<el-table-column sortable prop="status" label="状态"> </el-table-column>
<el-table-column sortable prop="liveSecs" label="时长(s)"> </el-table-column>
<el-table-column sortable prop="rePullCount" label="重试次数"> </el-table-column>
<el-table-column sortable prop="totalReaderCount" label="观看人数"> </el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button size="mini" type="danger"
@click="delStreamProxy(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-form>
</div>
</div>
<div v-if="selectIndex==='4'">
<el-form>
<!-- <el-form-item label="api操作密钥" label-width="180px">
<el-input v-model="secret" disabled></el-input>
</el-form-item> -->
<el-form-item label="虚拟主机" label-width="180px">
<el-input v-model="addStreamPusherProxy_params.vhost"></el-input>
</el-form-item>
<el-form-item label="" label-width="180px">
<el-select v-model="addStreamPusherProxy_params.schema" style="width: 100%;">
<el-option label="RTSP" value="rtsp"> </el-option>
<el-option label="RTMP" value="rtmp"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="应用名" label-width="180px">
<el-input v-model="addStreamPusherProxy_params.app"></el-input>
</el-form-item>
<el-form-item label="流id" label-width="180px">
<el-input v-model="addStreamPusherProxy_params.stream"></el-input>
</el-form-item>
<el-form-item label="转推地址" label-width="180px">
<el-input v-model="addStreamPusherProxy_params.dst_url"
placeholder="例如rtmp://live.hkstv.hk.lxdns.com/live/hks2"></el-input>
</el-form-item>
<el-form-item label="推流方式" label-width="180px">
<el-select v-model="addStreamPusherProxy_params.rtp_type" style="width: 100%;">
<el-option label="TCP" value="0"> </el-option>
<el-option label="UDP" value="1"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="超时时间" label-width="180px">
<el-input v-model="addStreamPusherProxy_params.timeout_sec"></el-input>
</el-form-item>
<el-form-item label="重试次数" label-width="180px">
<el-input v-model="addStreamPusherProxy_params.retry_count"></el-input>
</el-form-item>
<el-form-item label="">
<!-- <el-input type="textarea" :rows="5" v-model="addStreamPusherProxy_apiurl" readonly></el-input> -->
<div style="width: 100%;text-align: right;">
<el-button type="primary" @click="addStreamPusherProxy">增加</el-button>
<el-button type="primary" icon="el-icon-refresh" @click="listStreamPusherProxy">刷新</el-button>
</div>
</el-form-item>
</el-form>
<el-table :data="pusherProxyList" empty-text="暂无推流代理">
<!-- <el-table-column sortable prop="key" label="key"> </el-table-column> -->
<el-table-column sortable prop="url" label="url"> </el-table-column>
<el-table-column sortable prop="src.app" label="app"> </el-table-column>
<el-table-column sortable prop="src.stream" label="stream"> </el-table-column>
<el-table-column sortable prop="status" label="状态"> </el-table-column>
<el-table-column sortable prop="liveSecs" label="时长(s)"> </el-table-column>
<el-table-column sortable prop="rePublishCount" label="重试次数"> </el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button size="mini" type="danger"
@click="delStreamPusherProxy(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div v-show="selectIndex==='5'">
<el-form>
<el-form-item label="源地址" label-width="180px">
<el-input v-model="addFFmpeg_param.src_url"></el-input>
</el-form-item>
<el-form-item label="目的地址" label-width="180px">
<el-input v-model="addFFmpeg_param.dst_url"></el-input>
</el-form-item>
<el-form-item label="命令模板" label-width="180px">
<el-input v-model="addFFmpeg_param.ffmpeg_cmd_key"></el-input>
</el-form-item>
<el-form-item label="" label-width="180px">
<el-checkbox v-model="addFFmpeg_param.enable_mp4">MP4录制</el-checkbox>
<el-checkbox v-model="addFFmpeg_param.enable_hls">HLS录制</el-checkbox>
</el-form-item>
<el-form-item label="超时ms" label-width="180px">
<el-input v-model="addFFmpeg_param.timeout_ms"></el-input>
</el-form-item>
<el-form-item label="">
<el-button type="primary" @click="addFFmpegSource">增加</el-button>
<el-button type="primary" icon="el-icon-refresh" @click="listFFmpegSource">刷新</el-button>
</el-form-item>
</el-form>
<el-table :data="ffmpeglist" empty-text="暂无数据">
<el-table-column sortable prop="src_url" label="源地址"> </el-table-column>
<el-table-column sortable prop="dst_url" label="目的地址"> </el-table-column>
<el-table-column sortable prop="ffmpeg_cmd_key" label="命令模板"></el-table-column>
<el-table-column sortable prop="cmd" label="命令行"> </el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button size="mini" type="danger"
@click="delFFmpegSource(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div v-show="selectIndex==='6'">
<el-form>
<el-form-item label="虚拟主机" label-width="180px">
<el-input v-model="addRtpServer_param.vhost"></el-input>
</el-form-item>
<el-form-item label="应用名" label-width="180px">
<el-input v-model="addRtpServer_param.app"></el-input>
</el-form-item>
<el-form-item label="流id" label-width="180px">
<el-input v-model="addRtpServer_param.stream_id"></el-input>
</el-form-item>
<el-form-item label="tcp模式" label-width="180px">
<el-select v-model="addRtpServer_param.tcp_mode" style="width: 100%;">
<el-option v-for="(val,key) in typeTcpMode" :label="val" :value="key"></el-option>
</el-select>
</el-form-item>
<el-form-item label="流过滤" label-width="180px">
<el-select v-model="addRtpServer_param.only_track" style="width: 100%;">
<el-option v-for="(val,key) in typeOnlyTrack" :label="val" :value="key"></el-option>
</el-select>
</el-form-item>
<el-form-item label="本地ip" label-width="180px">
<el-input v-model="addRtpServer_param.local_ip"></el-input>
</el-form-item>
<el-form-item label="端口" label-width="180px">
<el-input v-model="addRtpServer_param.port">
<template #append>
<el-checkbox v-model="addRtpServer_param.re_use_port" label="端口复用"/>
</template>
</el-input>
</el-form-item>
<el-form-item label="SSRC" label-width="180px">
<el-input v-model="addRtpServer_param.ssrc"></el-input>
</el-form-item>
<el-form-item label="">
<el-button type="primary" @click="openRtpServer">增加</el-button>
<el-button type="primary" icon="el-icon-refresh" @click="listRtpServer">刷新</el-button>
</el-form-item>
</el-form>
<el-table :data="rtpserverlist" empty-text="暂无数据">
<el-table-column sortable prop="vhost" label="vhost"> </el-table-column>
<el-table-column sortable prop="app" label="app"> </el-table-column>
<el-table-column sortable prop="stream_id" label="stream"> </el-table-column>
<el-table-column sortable prop="port" label="端口"></el-table-column>
<el-table-column sortable prop="tcp_mode" label="tcp模式">
<template slot-scope="scope">
{{typeTcpMode[scope.row.tcp_mode]}}
</template>
</el-table-column>
<el-table-column sortable prop="only_track" label="流过滤">
<template slot-scope="scope">
{{typeOnlyTrack[scope.row.only_track]}}
</template>
</el-table-column>
<el-table-column label="ssrc" width="160">
<template slot-scope="scope">
<el-input v-model="scope.row.ssrc" class="input-with-select">
<template #append>
<el-button icon="el-icon-refresh" @click="updateRtpServerSSRC(scope.row)"></el-button>
</template>
</el-input>
</template>
</el-table-column>
<el-table-column prop="dst_url" label="目的地址" width="280">
<template slot-scope="scope">
<div style="display: flex;">
<el-input placeholder="ip" v-model="scope.row.dst_url" style="flex:4;"></el-input>
<el-input placeholder="port" v-model="scope.row.dst_port" style="flex:2"></el-input>
<el-button size="small" @click="connectRtpServer(scope.$index, scope.row)">连接</el-button>
</div>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button size="mini" type="danger"
@click="closeRtpServer(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div v-if="selectIndex==='7'">
<el-tabs tab-position="left" style="height: 100%;">
<el-tab-pane label="通用设置">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
<div class="confs">
<div class="conf_item">
<div class="conf_item_label">
check_nvidia_dev
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.general.check_nvidia_dev" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
启用虚拟主机
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.general.enableVhost" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
服务器唯一id
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.general.mediaServerId"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
启用FFMPEG日志
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.general.enable_ffmpeg_log" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
流超时时间(ms)
</div>
<div class="conf_item_value">
<el-input type="number"
v-model="serverConfig.general.maxStreamWaitMS"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
合并写缓存(ms)
</div>
<div class="conf_item_value">
<el-input type="number"
v-model="serverConfig.general.mergeWriteMS"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
断连删除
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.general.resetWhenRePlay" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
无人观看流的释放超时(ms)
</div>
<div class="conf_item_value">
<el-input type="number"
v-model="serverConfig.general.streamNoneReaderDelayMS"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
未就绪缓存帧数
</div>
<div class="conf_item_value">
<el-input type="number"
v-model="serverConfig.general.unready_frame_cache"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
加流超时(ms)
</div>
<div class="conf_item_value">
<el-input type="number"
v-model="serverConfig.general.wait_add_track_ms"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
流就绪超时(ms)
</div>
<div class="conf_item_value">
<el-input type="number"
v-model="serverConfig.general.wait_track_ready_ms"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
on_flow_report事件阈值
</div>
<div class="conf_item_value">
<el-input type="number"
v-model="serverConfig.general.flowThreshold"></el-input>
</div>
</div>
</div>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="FFMPEG设置">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="confs">
<div class="conf_item">
<div class="conf_item_label">
ffmpeg路径
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.ffmpeg.bin"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
拉流再推流命令模板
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.ffmpeg.cmd"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
日志路径
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.ffmpeg.log"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
自动重启时间
</div>
<div class="conf_item_value">
<el-input type="number"
v-model="serverConfig.ffmpeg.restart_sec"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
截图模板
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.ffmpeg.snap"></el-input>
</div>
</div>
</div>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="API设置">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="confs">
<div class="conf_item">
<div class="conf_item_label">
调试
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.api.apiDebug" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
密钥
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.api.secret"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
截图路径
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.api.snapRoot"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
缺省截图
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.api.defaultSnap"></el-input>
</div>
</div>
</div>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="Hook设置">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="confs">
<div class="conf_item">
<div class="conf_item_label">
启用hook事件
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.hook.enable" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item" v-if="serverConfig.hook.enable=='1'">
<div class="conf_item_label">
alive心跳间隔(s)
</div>
<div class="conf_item_value">
<el-input type="number"
v-model="serverConfig.hook.alive_interval"></el-input>
</div>
</div>
<div class="conf_item" v-if="serverConfig.hook.enable=='1'">
<div class="conf_item_label">
Hook请求超时(s)
</div>
<div class="conf_item_value">
<el-input type="number"
v-model="serverConfig.hook.timeoutSec"></el-input>
</div>
</div>
<div class="conf_item" v-if="serverConfig.hook.enable=='1'">
<div class="conf_item_label">
失败重试次数
</div>
<div class="conf_item_value">
<el-input type="number" v-model="serverConfig.hook.retry"></el-input>
</div>
</div>
<div class="conf_item" v-if="serverConfig.hook.enable=='1'">
<div class="conf_item_label">
失败重试延时(s)
</div>
<div class="conf_item_value">
<el-input type="number"
v-model="serverConfig.hook.retry_delay"></el-input>
</div>
</div>
</div>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12"
v-if="serverConfig.hook.enable=='1'">
<div class="confs">
<div class="conf_item">
<div class="conf_item_label">
保活上报
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.hook.on_server_keepalive"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
流量事件
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.hook.on_flow_report"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
http文件鉴权事件
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.hook.on_http_access"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
播放鉴权事件
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.hook.on_play"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
推流鉴权事件
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.hook.on_publish"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
mp4切片录好事件
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.hook.on_record_mp4"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
ts切片录好事件
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.hook.on_record_ts"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
rtp服务超时事件
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.hook.on_rtp_server_timeout"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
rtsp播放鉴权事件
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.hook.on_rtsp_auth"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
rtsp专属鉴权事件
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.hook.on_rtsp_realm"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
发送rtp被动关闭
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.hook.on_send_rtp_stopped"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
服务启动事件
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.hook.on_server_started"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
服务关闭事件
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.hook.on_server_exited"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
telnet调试鉴权事件
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.hook.on_shell_login"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
流注册或注销事件
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.hook.on_stream_changed"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
无人观看流事件
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.hook.on_stream_none_reader"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
播放未找到流事件
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.hook.on_stream_not_found"></el-input>
</div>
</div>
</div>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="HLS设置">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="confs">
<div class="conf_item">
<div class="conf_item_label">
广播hls切片完成
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.hls.broadcastRecordTs" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
删除延时(s)
</div>
<div class="conf_item_value">
<el-input type="number"
v-model="serverConfig.hls.deleteDelaySec"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
文件缓存大小
</div>
<div class="conf_item_value">
<el-input type="number"
v-model="serverConfig.hls.fileBufSize"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
切片时长(s)
</div>
<div class="conf_item_value">
<el-input type="number" v-model="serverConfig.hls.segDur"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
切片个数
</div>
<div class="conf_item_value">
<el-input type="number" v-model="serverConfig.hls.segNum"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
预留切片数
</div>
<div class="conf_item_value">
<el-input type="number" v-model="serverConfig.hls.segRetain"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
保留hls文件
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.hls.segKeep" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
</div>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="cluster设置">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="confs">
<div class="conf_item">
<div class="conf_item_label">
源站拉流url模板
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.cluster.origin_url"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
溯源总超时
</div>
<div class="conf_item_value">
<el-input type="number"
v-model="serverConfig.cluster.timeout_sec"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
溯源失败重试次数
</div>
<div class="conf_item_value">
<el-input type="number"
v-model="serverConfig.cluster.retry_count"></el-input>
</div>
</div>
</div>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="HTTP">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="confs">
<div class="conf_item">
<div class="conf_item_label">
端口
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.http.port"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
SSL端口
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.http.sslport"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
编码
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.http.charSet" placeholder="请选择" style="width: 100%;">
<el-option label="UTF-8" value="utf-8"></el-option>
<el-option label="GB2312" value="gb2312"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
超时时间
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.http.keepAliveSecond"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
最大请求大小(字节)
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.http.maxReqSize"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
404网页内容
</div>
<div class="conf_item_value">
<el-input type="textarea"
v-model="serverConfig.http.notFound"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
根目录
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.http.rootPath"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
发送缓存大小
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.http.sendBufSize"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
禁止使用mmap缓存的文件后缀
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.http.forbidCacheSuffix"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
forwarded_ip_header
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.http.forwarded_ip_header"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
显示目录列表
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.record.dirMenu" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
虚拟路径
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.http.virtualPath"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
允许跨域请求
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.record.allow_cross_domains" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
Ip白名单
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.http.allow_ip_range"></el-input>
</div>
</div>
</div>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="protocol设置">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="confs">
<div class="conf_item">
<div class="conf_item_label">
开启音频
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.protocol.enable_audio" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
添加静音音轨
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.protocol.add_mute_audio" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
<el-tooltip effect="dark" placement="bottom-start">
<div slot="content">
推流断开后可以在超时时间内重新连接上继续推流,这样播放器会接着播放。
<br />置0关闭此特性(推流断开会导致立即断开播放器)
<br />此参数不应大于播放器超时时间;单位ms
</div>
<span>继续推流时间(ms)</span>
</el-tooltip>
</div>
<div class="conf_item_value">
<el-input type="number"
v-model="serverConfig.protocol.continue_push_ms"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
将mp4录制当做观看者
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.protocol.mp4_as_player" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
mp4切片大小(s)
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.protocol.mp4_max_second"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
mp4录像保存路径
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.protocol.mp4_save_path"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
hls录像保存路径
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.protocol.hls_save_path"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
开启帧级时间戳覆盖
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.protocol.modify_stamp"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
无人观看时,直接关闭
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.protocol.auto_close" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
</div>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="confs">
<div class="conf_item">
<div class="conf_item_label">
启用 http-fmp4/ws-fmp4
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.protocol.enable_fmp4" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
启用 hls
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.protocol.enable_hls" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
启用MP4录制
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.protocol.enable_mp4" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
启用 rtmp/flv
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.protocol.enable_rtmp" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
启用 rtsp
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.protocol.enable_rtsp" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
启用 http-ts/ws-ts
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.protocol.enable_ts" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
</div>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="confs">
<div class="conf_item">
<div class="conf_item_label">
按需生成 http[s]-fmp4、ws[s]-fmp4
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.protocol.fmp4_demand" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
按需生成 hls
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.protocol.hls_demand" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
按需生成 rtmp[s]、http[s]-flv、ws[s]-flv
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.protocol.rtmp_demand" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
按需生成 rtsp[s]
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.protocol.rtsp_demand" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
按需生成 http[s]-ts
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.protocol.ts_demand" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
</div>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="组播设置">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="confs">
<div class="conf_item">
<div class="conf_item_label">
组播udp ttl
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.multicast.udpTTL"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
rtp组播起始地址
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.multicast.addrMin"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
rtp组播截止地址
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.multicast.addrMax"></el-input>
</div>
</div>
</div>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="RECORD">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="confs">
<div class="conf_item">
<div class="conf_item_label">
应用名
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.record.appName"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
fastStart
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.record.fastStart" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
文件缓存大小
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.record.fileBufSize"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
保存路径
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.record.filePath"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
循环播放
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.record.fileRepeat" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
fileSecond
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.record.fileSecond"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
MP4点播每次流化数据量
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.record.sampleMS"></el-input>
</div>
</div>
</div>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="RTC">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="confs">
<div class="conf_item">
<div class="conf_item_label">
公网ip
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.rtc.externIP"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
UDP端口
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.rtc.port"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
TCP端口
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.rtc.tcpPort"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
rtc超时
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.rtc.timeoutSec"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
remb比特率
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.rtc.rembBitRate"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
音频候选编码
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.rtc.preferredCodecA"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
视频候选编码
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.rtc.preferredCodecV"></el-input>
</div>
</div>
</div>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="RTMP">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="confs">
<div class="conf_item">
<div class="conf_item_label">
端口
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.rtmp.port"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
SSL端口
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.rtmp.sslport"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
握手超时
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.rtmp.handshakeSecond"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
心跳超时(s)
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.rtmp.keepAliveSecond"></el-input>
</div>
</div>
</div>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="RTSP">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="confs">
<div class="conf_item">
<div class="conf_item_label">
端口
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.rtsp.port"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
SSL端口
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.rtsp.sslport"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
低延迟模式
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.rtsp.lowLatency" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
心跳超时(s)
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.rtsp.keepAliveSecond"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
握手超时(s)
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.rtsp.handshakeSecond"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
直接代理模式
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.rtsp.directProxy" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
rtsp专有鉴权
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.rtsp.authBasic"></el-input>
</div>
</div>
</div>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="RTP">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="confs">
<div class="conf_item">
<div class="conf_item_label">
音频mtu大小
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.rtp.audioMtuSize"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
视频mtu大小
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.rtp.videoMtuSize"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
低延迟开关
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.rtp.lowLatency" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
rtp包长度限制
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.rtp.rtpMaxSize"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
采用stap-a模式
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.rtp.h264_stap_a" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
</div>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="confs">
<div class="conf_item">
<div class="conf_item_label">
调试输出目录(包括rtp/ps/h264)
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.rtp_proxy.dumpDir"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
udp和tcp代理服务端口
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.rtp_proxy.port"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
端口范围
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.rtp_proxy.port_range"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
超时时间
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.rtp_proxy.timeoutSec"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
开启gop缓存优化
</div>
<div class="conf_item_value">
<el-select v-model="serverConfig.rtp_proxy.gop_cache" placeholder="请选择" style="width: 100%;">
<el-option v-for="(val,key) in yesNo" :label="val" :value="key"></el-option>
</el-select>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
g711a载荷类型
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.rtp_proxy.g711a_pt"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
g711u载荷类型
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.rtp_proxy.g711u_pt"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
h264载荷类型
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.rtp_proxy.h264_pt"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
h265载荷类型
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.rtp_proxy.h265_pt"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
opus载荷类型
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.rtp_proxy.opus_pt"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
ps载荷类型
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.rtp_proxy.ps_pt"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
ts载荷类型
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.rtp_proxy.ts_pt"></el-input>
</div>
</div>
</div>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="SHELL">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="confs">
<div class="conf_item">
<div class="conf_item_label">
端口
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.shell.port"></el-input>
</div>
</div>
<div class="conf_item" v-if="serverConfig.shell.port!='0'">
<div class="conf_item_label">
最大请求大小
</div>
<div class="conf_item_value">
<el-input type="text"
v-model="serverConfig.shell.maxReqSize"></el-input>
</div>
</div>
</div>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="SRT">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="confs">
<div class="conf_item">
<div class="conf_item_label">
延迟估算参数
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.srt.latencyMul"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
包缓存大小
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.srt.pktBufSize"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
端口
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.srt.port"></el-input>
</div>
</div>
<div class="conf_item">
<div class="conf_item_label">
会话超时(s)
</div>
<div class="conf_item_value">
<el-input type="text" v-model="serverConfig.srt.timeoutSec"></el-input>
</div>
</div>
</div>
</el-col>
</el-row>
</el-tab-pane>
</el-tabs>
<el-form ref="form" :model="serverConfig" label-width="180px">
<el-form-item>
<el-button type="primary" @click="onSubmit">保存更新</el-button>
<el-button>取消</el-button>
</el-form-item>
</el-form>
</div>
</el-main>
<el-footer>
<span>分支:{{ versioninfo.branchName }}</span>
<span>构建时间: {{ versioninfo.buildTime }}</span>
<span>版本: {{ versioninfo.commitHash }}</span>
</el-footer>
</el-container>
</div>
</body>
<script src="./js/vue.min.js"></script>
<script src="./assets/elementui/index.js"></script>
<script src="./js/axios.min.js"></script>
<script src="./js/qs.js"></script>
<script src="./js/echarts.min.js"></script>
<script src="./js/ZLMRTCClient.js"></script>
<script>
new Vue({
el: '#app',
beforeMount() {
var urlParams = new URLSearchParams(window.location.search);
var secret = urlParams.get('secret');
console.log('secret值为:', secret);
if (secret) this.secret = secret;
else this.secret = "";
var host = urlParams.get('host');
console.log('host值为:', host);
if (host) this.host = host;
else this.host = "";
if (this.secret) {
//获取版本和配置信息
this.version();
this.getServerConfig();
this.getApiList();
}
//获取支持的分辨率
this.resolution_opt = []
ZLMRTCClient.GetAllScanResolution().forEach((r, i) => {
this.resolution_opt.push({
text: r.label + "(" + r.width + "x" + r.height + ")",
value: r
})
})
this.webrtc.zlmsdpUrl = document.location.protocol + "//" + window.location.host + "/index/api/webrtc?app=live&stream=test&type=play"
},
mounted() {
if (this.secret == "") {
this.$message({
message: '在url路径中添加正确的secret参数',
type: 'error'
});
return
}
else {
this.updatetimer = setInterval(this.update_status, 1000)
}
this.chart1 = echarts.init(this.$refs.chart1);
this.chart2 = echarts.init(this.$refs.chart2);
this.chart3 = echarts.init(this.$refs.chart3);
this.getMediaList();
this.getAllSession();
},
data: function () {
return {
host: "",
secret: "",
selectIndex: '1',
yesNo:{
0:'',
1:'',
},
typeTcpMode:{
0:"",
1:"被动",
2:"主动"
},
typeOnlyTrack:{
0:"全部",
1:"只音频",
2:"只视频",
},
getMediaList_queryparams: {
schema: null,
vhost: "__defaultVhost__",
app: null,
stream: null
},
addStreamProxy_params: {
vhost: "__defaultVhost__",
app: "live",
stream: "test",
url: "",
retry_count: -1,
rtp_type: "0",
timeout_sec: 5,
enable_hls: false,
enable_hls_fmp4: false,
enable_mp4: false,
enable_rtsp: true,
enable_rtmp: true,
enable_ts: true,
enable_fmp4: true,
hls_demand: false,
rtsp_demand: false,
rtmp_demand: false,
ts_demand: false,
fmp4_demand: false,
enable_audio: true,
add_mute_audio: true,
mp4_save_path: "",
mp4_max_second: 10,
mp4_as_player: false,
hls_save_path: "",
modify_stamp: "",
auto_close: false
},
addStreamPusherProxy_params: {
vhost: "__defaultVhost__",
app: "live",
stream: "test",
schema: "rtsp",
dst_url: "",
retry_count: -1,
rtp_type: "0",
timeout_sec: 5,
},
versioninfo: {
},
updatetimer: null,
autorefresh_medialist: false,
autorefresh_session: false,
serverConfig: null,
serverConfig_bak: null,
chart1: null,
chart2: null,
chart3: null,
threadsLoad: [],
workThreadsLoad: [],
statistic: null,
medialist: [],
ffmpeglist: [],
addFFmpeg_param: {
src_url: "",
dst_url: "",
ffmpeg_cmd_key: "ffmpeg.cmd",
timeout_ms: 10000,
enable_hls: false,
enable_mp4: false,
},
rtpserverlist: [],
addRtpServer_param:{
vhost: "__defaultVhost__",
app: "rtp",
stream_id: "test",
tcp_mode: "1",
only_track: "0",
local_ip: '',
re_use_port: true,
port: 0,
ssrc: 0,
},
pusherProxyList: [],
streamProxyList: [],
playerlist: [],
playerTitle: "PlayerList",
showPlayerDialog: false,
sessionlist: [],
schemaFilters:[
{text:'rtsp', value: 'rtsp'},
{text:'rtmp', value: 'rtmp'},
{text:'ts', value: 'ts'},
{text:'hls', value: 'hls'},
{text:'fmp4', value: 'fmp4'},
],
webrtc: {
debug: true,
zlmsdpUrl: "",
type: "play",
recvOnly: true,
resolution: "",
usedatachannel: false,
simulcast: false,
useCamera: true,
audioEnable: true,
videoEnable: true,
msgsend: "",
msgrecv: "",
},
resolution_opt: [],
webrtc_player: null,
getAllSession_queryparams: {
local_port: null,
peer_ip: null
}
}
},
filters: {
bitsSpeed: function (val) {
return byteString(val * 8);
},
msFormat: function(val) {
var time = new Date(val);
return time.toLocaleString();
},
secFormat: function(val) {
var time = new Date(val * 1000);
return time.toLocaleString();
}
},
computed: {
apiurl: function () {
const qs_str = Qs.stringify(this.addStreamProxy_params, {
filter: (key, value) => {
if (value === "" || value === null || value === undefined) {
return undefined; // 返回 undefined 将排除该属性
}
return value;
}
})
console.log(qs_str)
return `/index/api/addStreamProxy?secret=${this.secret}&${qs_str}`
},
addStreamPusherProxy_apiurl: function () {
const qs_str = Qs.stringify(this.addStreamPusherProxy_params, {
filter: (key, value) => {
if (value === "" || value === null || value === undefined) {
return undefined; // 返回 undefined 将排除该属性
}
return value;
}
})
console.log(qs_str)
return `/index/api/addStreamPusherProxy?secret=${this.secret}&${qs_str}`
},
addFFmpegSource_apiurl: function () {
const qs_str = Qs.stringify(this.addFFmpeg_param, {
filter: (key, value) => {
if (value === "" || value === null || value === undefined) {
return undefined; // 返回 undefined 将排除该属性
}
return value;
}
})
console.log(qs_str)
return `/index/api/addFFmpegSource?secret=${this.secret}&${qs_str}`
},
},
watch: {
'webrtc.type'(newv, oldv) {
var url = new URL(this.webrtc.zlmsdpUrl)
url.searchParams.set("type", newv)
this.webrtc.zlmsdpUrl = url.toString()
if (newv == "play") {
this.webrtc.recvOnly = true;
} else if (newv == "echo") {
this.webrtc.recvOnly = false;
} else {
this.webrtc.recvOnly = false;
}
}
},
methods: {
filterSchema(value, row) {
return row.schema === value;
},
startwebrtc() {
if (this.webrtc.resolution == "") {
this.$message({
message: '请选择分辨率(please set resolution)',
type: 'warning'
});
return
}
this.webrtc_player = new ZLMRTCClient.Endpoint(
{
element: this.$refs.video,// video 标签
debug: this.webrtc.debug,// 是否打印日志
zlmsdpUrl: this.webrtc.zlmsdpUrl,//流地址
simulcast: this.webrtc.simulcast,
useCamera: this.webrtc.useCamera,
audioEnable: this.webrtc.audioEnable,
videoEnable: this.webrtc.videoEnable,
recvOnly: this.webrtc.recvOnly,
resolution: {
w: this.resolution_opt[this.webrtc.resolution].value.width,
h: this.resolution_opt[this.webrtc.resolution].value.height
},
usedatachannel: this.webrtc.usedatachannel,
});
this.webrtc_player.on(ZLMRTCClient.Events.WEBRTC_ICE_CANDIDATE_ERROR, (e) => {// ICE 协商出错
console.log('ICE 协商出错')
this.$message({
message: 'ICE 协商出错',
type: 'warning'
});
});
this.webrtc_player.on(ZLMRTCClient.Events.WEBRTC_ON_REMOTE_STREAMS, (e) => {//获取到了远端流,可以播放
this.$message({
message: '播放成功',
type: 'success'
});
console.log('播放成功', e.streams)
});
this.webrtc_player.on(ZLMRTCClient.Events.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED, (e) => {// offer anwser 交换失败
console.log('offer anwser 交换失败', e)
this.$message({
message: `offer anwser 交换失败:${e.msg}`,
type: 'error'
});
this.stopwebrtc();
});
this.webrtc_player.on(ZLMRTCClient.Events.WEBRTC_ON_LOCAL_STREAM, (s) => {// 获取到了本地流
this.$refs.selfVideo.srcObject = s;
this.$refs.selfVideo.muted = true;
});
this.webrtc_player.on(ZLMRTCClient.Events.CAPTURE_STREAM_FAILED, (s) => {// 获取本地流失败
this.$message({
message: '获取本地流失败',
type: 'error'
});
console.log('获取本地流失败')
});
this.webrtc_player.on(ZLMRTCClient.Events.WEBRTC_ON_CONNECTION_STATE_CHANGE, (state) => {// RTC 状态变化 ,详情参考 https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/connectionState
console.log('当前状态==>', state)
});
this.webrtc_player.on(ZLMRTCClient.Events.WEBRTC_ON_DATA_CHANNEL_OPEN, (event) => {
console.log('rtc datachannel 打开 :', event)
this.$message({
message: 'rtc datachannel 打开',
type: 'info'
});
});
this.webrtc_player.on(ZLMRTCClient.Events.WEBRTC_ON_DATA_CHANNEL_MSG, (event) => {
console.log('rtc datachannel 消息 :', event.data)
this.webrtc.msgrecv = event.data
});
this.webrtc_player.on(ZLMRTCClient.Events.WEBRTC_ON_DATA_CHANNEL_ERR, (event) => {
console.log('rtc datachannel 错误 :', event)
this.$message({
message: 'rtc datachannel 错误 ',
type: 'error'
});
});
this.webrtc_player.on(ZLMRTCClient.Events.WEBRTC_ON_DATA_CHANNEL_CLOSE, (event) => {
console.log('rtc datachannel 关闭 :', event)
this.$message({
message: 'rtc datachannel 关闭 ',
type: 'warning'
});
});
},
stopwebrtc() {
if (this.webrtc_player) {
this.webrtc_player.close();
this.webrtc_player = null;
if (this.$refs.video) {
this.$refs.video.srcObject = null;
this.$refs.video.load();
}
this.$refs.selfVideo.srcObject = null;
this.$refs.selfVideo.load();
}
},
sendata() {
console.log(`发送数据:${this.webrtc.msgsend}`)
if (this.webrtc_player) {
this.webrtc_player.sendMsg(this.webrtc.msgsend)
}
},
closedata() {
console.log(`关闭数据通道`)
if (this.webrtc_player) {
this.webrtc_player.closeDataChannel()
this.$message({
message: '关闭数据通道',
type: 'success'
});
}
},
onSubmit() {
this.setServerConfig()
},
handleSelect(key, keyPath) {
if (this.updatetimer) {
clearInterval(this.updatetimer);
this.updatetimer = null;
}
if (key) this.selectIndex = key;
if (this.selectIndex == '7') {
this.getServerConfig();
}
else if (this.selectIndex == '3') {
this.listStreamProxy();
}
else if (this.selectIndex == '4') {
this.listStreamPusherProxy();
}
else if (this.selectIndex == '5') {
this.listFFmpegSource();
}
else if (this.selectIndex == '6') {
this.listRtpServer();
}
else if (this.selectIndex == '2') {
var ishttps = 'https:' == document.location.protocol ? true : false
var isLocal = ("file:" == document.location.protocol) || (document.location.host == "127.0.0.1") || (document.location.host == "localhost");
if (!ishttps && !isLocal) {
this.$message({
message: '本demo需要在https的网站访问 ,如果你要推流的话(this demo must access in site of https if you want push stream)',
type: 'warning'
});
}
}
else if (this.selectIndex == '1') {
this.chart1 = echarts.init(this.$refs.chart1);
this.chart2 = echarts.init(this.$refs.chart2);
this.chart3 = echarts.init(this.$refs.chart3);
this.updatetimer = setInterval(this.update_status, 1000)
}
console.log(key, keyPath);
},
async performRequest(url, successMessage, errorMessage, callback) {
try {
const response = await axios.get(url);
if (response.status === 200) {
if (response.data.code === 0) {
if (successMessage) {
this.$message({
message: successMessage,
type: 'success',
});
}
if (callback) {
callback(response);
}
} else {
this.$message({
message: errorMessage || response.data.msg,
type: 'error',
});
}
}
else {
this.$message({
message: `response.status:${response.status}`,
type: 'error',
});
}
} catch (err) {
// 错误处理代码
}
},
addStreamProxy() {
const url = `${this.host}${this.apiurl}`;
this.performRequest(url, '添加成功!', '', () => this.listStreamProxy());
},
addStreamPusherProxy() {
const url = `${this.host}${this.addStreamPusherProxy_apiurl}`;
this.performRequest(url, '添加成功!', '', () => this.listStreamPusherProxy());
},
delStreamProxy(index, row) {
console.log(index, row);
const url = `${this.host}/index/api/delStreamProxy?secret=${this.secret}&key=${row.key}`;
this.performRequest(url, '删除成功!', '', () => this.listStreamProxy());
},
delStreamPusherProxy(index, row) {
console.log(index, row);
const url = `${this.host}/index/api/delStreamPusherProxy?secret=${this.secret}&key=${row.key}`;
this.performRequest(url, '删除成功!', '', () => this.listStreamPusherProxy());
},
listStreamProxy() {
const url = `${this.host}/index/api/listStreamProxy?secret=${this.secret}`;
this.performRequest(url, "", "", resp => {
if (resp.data.data) this.streamProxyList = resp.data.data;
else this.streamProxyList = [];
})
},
listStreamPusherProxy() {
const url = `${this.host}/index/api/listStreamPusherProxy?secret=${this.secret}`;
this.performRequest(url, "", "", resp => {
if (resp.data.data) this.pusherProxyList = resp.data.data;
else this.pusherProxyList = [];
})
},
close_stream(index, row) {
console.log(index, row);
const data = {
secret: this.secret,
schema: row.schema,
vhost: row.vhost,
app: row.app,
stream: row.stream,
force: true
}
const url = `${this.host}/index/api/close_streams?${Qs.stringify(data)}`;
this.performRequest(url, '关闭成功!', '', () => this.getMediaList());
},
kick_session(id) {
const url = `${this.host}/index/api/kick_session?secret=${this.secret}&id=${id}`;
this.performRequest(url, '关闭成功!', '', () => this.getAllSession());
},
getApiList() {
const url = `${this.host}/index/api/getApiList?secret=${this.secret}`;
this.performRequest(url, '', '', (response) => {
console.log(response.data.data);
});
},
getPlayerList(row) {
const url = `${this.host}/index/api/getMediaPlayerList?secret=${this.secret}&schema=${row.schema}&vhost=${row.vhost}&app=${row.app}&stream=${row.stream}`;
console.log(url);
this.performRequest(url, '', '', (resp) => {
console.log(resp.data.data);
if (resp.data.data) this.playerlist = resp.data.data;
else this.playerlist = [];
if (this.playerlist.length) {
this.playerTitle = `${row.app}\\${row.stream}’s PlayerList`;
this.showPlayerDialog = true;
}
});
},
getServerConfig() {
const url = `${this.host}/index/api/getServerConfig?secret=${this.secret}`;
this.performRequest(url, '', '', (response) => {
var data = {}
var serverConfig = response.data.data[0]
console.log(serverConfig);
const serverConfigKeys = Object.keys(serverConfig);
for (const key of serverConfigKeys) {
const [category, subKey] = key.split('.');
if (!data[category]) {
data[category] = {};
}
data[category][subKey] = serverConfig[key];
}
this.serverConfig = data;
this.serverConfig_bak = JSON.parse(JSON.stringify(data));
});
},
setServerConfig() {
var confs = findDifferentProperties(this.serverConfig_bak, this.serverConfig)
console.log(confs)
const flattened = flattenObject(confs);
const queryString = Object.keys(flattened).map(key => `${key}=${flattened[key]}`).join('&');
if (queryString == "") {
this.$message({
message: '没有修改任何参数',
type: 'info'
});
return
}
const update_counts = ((queryString.match(/&/g) || []).length + 1)
const postdata = { ...{ secret: this.secret }, ...flattened }
axios.post(`${this.host}/index/api/setServerConfig`, postdata).then(resp => {
if (resp.status == 200) {
if (resp.data.code === 0) {
if (update_counts == resp.data.changed) {
this.$message({
message: `保存成功!共修改${resp.data.changed}个参数`,
type: 'success'
});
}
else {
this.$message({
message: `存在参数修改失败,共修改${resp.data.changed}个参数,请检查后重试!`,
type: 'error'
});
}
this.getServerConfig()
}
}
}).catch(err => {
console.log(err)
})
},
getThreadsLoad() {
const url = `${this.host}/index/api/getThreadsLoad?secret=${this.secret}`;
this.performRequest(url, "", "", resp => {
this.threadsLoad = resp.data.data;
var delays = this.threadsLoad.map(item => item.delay);
var loads = this.threadsLoad.map(item => item.load);
var max_delay = Math.max(...delays);
var y_max = max_delay>100?max_delay*1.2:100;
this.chart3.setOption({
title: {
text: 'ThreadsLoad'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
crossStyle: {
color: '#999'
}
}
},
legend: {
data: ['延迟', '负载']
},
xAxis: [
{
type: 'category',
data: Array.from({ length: this.threadsLoad.length }, (_, i) => i + 1),
axisPointer: {
type: 'shadow'
}
}
],
yAxis: [
{
type: 'value',
name: '延迟',
min: 0,
max: y_max,
axisLabel: {
formatter: '{value} ms'
}
},
{
type: 'value',
name: '负载',
min: 0,
max: 100,
axisLabel: {
formatter: '{value} %'
}
}
],
series: [
{
name: '延迟',
type: 'line',
tooltip: {
valueFormatter: function (value) {
return value + ' ms';
}
},
data: delays
},
{
name: '负载',
type: 'bar',
yAxisIndex: 1,
tooltip: {
valueFormatter: function (value) {
return value + ' %';
}
},
data: loads
}
]
})
})
},
getWorkThreadsLoad() {
const url = `${this.host}/index/api/getWorkThreadsLoad?secret=${this.secret}`;
this.performRequest(url, "", "", resp => {
this.workThreadsLoad = resp.data.data;
var delays = this.workThreadsLoad.map(item => item.delay);
var loads = this.workThreadsLoad.map(item => item.load);
var max_delay = Math.max(delays);
var y_max = max_delay>100?max_delay:100;
this.chart2.setOption({
title: {
text: 'WorkThreadsLoad'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
crossStyle: {
color: '#999'
}
}
},
legend: {
data: ['延迟', '负载']
},
xAxis: [
{
type: 'category',
data: Array.from({ length: this.workThreadsLoad.length }, (_, i) => i + 1),
axisPointer: {
type: 'shadow'
}
}
],
yAxis: [
{
type: 'value',
name: '延迟',
min: 0,
max: y_max,
axisLabel: {
formatter: '{value} ms'
}
},
{
type: 'value',
name: '负载',
min: 0,
max: 100,
axisLabel: {
formatter: '{value} %'
}
}
],
series: [
{
name: '延迟',
type: 'line',
tooltip: {
valueFormatter: function (value) {
return value + ' ms';
}
},
data: delays
},
{
name: '负载',
type: 'bar',
yAxisIndex: 1,
tooltip: {
valueFormatter: function (value) {
return value + ' %';
}
},
data: loads
}
]
})
})
},
getStatistic() {
const url = `${this.host}/index/api/getStatistic?secret=${this.secret}`;
this.performRequest(url, "", "", resp => {
this.statistic = resp.data.data;
this.chart1.setOption({
title: {
text: 'Statistic'
},
tooltip: {},
legend: {},
xAxis: {
data: Object.keys(this.statistic),
axisLabel: {
rotate: 45 // 设置X轴刻度标签旋转角度为45度
}
},
yAxis: {},
series: [{
type: 'bar',
data: Object.values(this.statistic)
}]
})
})
},
restartServer() {
const url = `${this.host}/index/api/restartServer?secret=${this.secret}`;
this.performRequest(url, "", "", resp => {
this.$message({
message: "服务器将在一秒后重启",
type: 'success'
});
})
},
version() {
const url = `${this.host}/index/api/version?secret=${this.secret}`;
this.performRequest(url, "", "", resp => {
this.versioninfo = resp.data.data;
console.log(this.versioninfo)
})
},
getMediaList() {
const url = `${this.host}/index/api/getMediaList?secret=${this.secret}&` + Qs.stringify(this.getMediaList_queryparams);
this.performRequest(url, "", "", resp => {
if (resp.data.data) this.medialist = resp.data.data;
else this.medialist = [];
})
},
listRtpServer() {
const url = `${this.host}/index/api/listRtpServer?secret=${this.secret}`;
this.performRequest(url, "", "", resp => {
if (resp.data.data) this.rtpserverlist = resp.data.data;
else this.rtpserverlist = [];
})
},
openRtpServer() {
const url = `${this.host}/index/api/openRtpServer?secret=${this.secret}&` + Qs.stringify(this.addRtpServer_param);
this.performRequest(url, '添加成功!', '', () => this.listRtpServer());
},
closeRtpServer(index, row) {
console.log(index, row);
const url = `${this.host}/index/api/closeRtpServer?secret=${this.secret}&stream_id=${row.stream_id}&vhost=${row.vhost}&app=${row.app}`;
this.performRequest(url, '删除成功!', '', () => this.listRtpServer());
},
connectRtpServer(index, row) {
console.log(index, row);
const url = `${this.host}/index/api/connectRtpServer?secret=${this.secret}&stream_id=${row.stream_id}&vhost=${row.vhost}&app=${row.app}&dst_url=${row.dst_url}&dst_port=${row.dst_port}`;
console.log(url);
this.performRequest(url, '连接成功!', '', () => this.listRtpServer());
},
updateRtpServerSSRC(row) {
const url = `${this.host}/index/api/updateRtpServerSSRC?secret=${this.secret}&stream_id=${row.stream_id}&vhost=${row.vhost}&app=${row.app}&ssrc=${row.ssrc}`;
console.log(url);
this.performRequest(url, '更新成功!', '', () => this.listRtpServer());
},
listFFmpegSource() {
const url = `${this.host}/index/api/listFFmpegSource?secret=${this.secret}`;
this.performRequest(url, "", "", resp => {
if (resp.data.data) this.ffmpeglist = resp.data.data;
else this.ffmpeglist = [];
})
},
delFFmpegSource(index, row) {
console.log(index, row);
const url = `${this.host}/index/api/delFFmpegSource?secret=${this.secret}&key=${row.key}`;
this.performRequest(url, '删除成功!', '', () => this.listFFmpegSource());
},
addFFmpegSource() {
const url = `${this.host}${this.addFFmpegSource_apiurl}`;
this.performRequest(url, '添加成功!', '', () => this.listFFmpegSource());
},
getAllSession() {
const url = `${this.host}/index/api/getAllSession?secret=${this.secret}&` + Qs.stringify(this.getAllSession_queryparams);
this.performRequest(url, "", "", resp => {
this.sessionlist = resp.data.data;
})
},
update_status() {
this.getThreadsLoad();
this.getWorkThreadsLoad();
this.getStatistic();
if (this.autorefresh_medialist)
this.getMediaList();
if (this.autorefresh_session)
this.getAllSession();
},
},
})
</script>
<style>
.el-header,
.el-footer {
background-color: #545c64;
color: #333;
text-align: center;
line-height: 60px;
}
.el-main {
background-color: #E9EEF3;
color: #333;
text-align: center;
/* line-height: 260px; */
}
body>.el-container {
margin-bottom: 40px;
}
.videobox {
width: 100%;
height: 100%;
}
.confs {
min-height: 50px;
border-radius: 4px;
background-color: #545c6421;
margin-bottom: 20px;
display: flex;
flex-direction: column;
}
.confs>.conf_item {
margin: 10px;
display: flex;
flex-direction: row;
justify-content: space-between;
line-height: 2em;
}
.confs>.conf_item>.conf_item_label {}
.confs>.conf_item>.conf_item_value {
width: 70%;
}
.input-with-select .el-input-group__prepend {
background-color: var(--el-fill-color-blank);
}
</style>
</html>
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
JavaScript
1
https://gitee.com/w3ipc/zlm_webassist.git
[email protected]:w3ipc/zlm_webassist.git
w3ipc
zlm_webassist
zlm_webassist
main

搜索帮助