diff --git a/src/main/java/com/genersoft/iot/vmp/media/bean/MediaInfo.java b/src/main/java/com/genersoft/iot/vmp/media/bean/MediaInfo.java
index ace469866..6c288e5e4 100644
--- a/src/main/java/com/genersoft/iot/vmp/media/bean/MediaInfo.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/bean/MediaInfo.java
@@ -33,6 +33,10 @@ public class MediaInfo {
     private Integer width;
     @Schema(description = "视频高度")
     private Integer height;
+    @Schema(description = "FPS")
+    private Integer fps;
+    @Schema(description = "丢包率")
+    private Integer loss;
     @Schema(description = "音频编码类型")
     private String audioCodec;
     @Schema(description = "音频通道数")
@@ -58,6 +62,7 @@ public class MediaInfo {
     @Schema(description = "服务ID")
     private String serverId;
 
+
     public static MediaInfo getInstance(JSONObject jsonObject, MediaServer mediaServer, String serverId) {
         MediaInfo mediaInfo = new MediaInfo();
         mediaInfo.setMediaServer(mediaServer);
@@ -112,6 +117,13 @@ public class MediaInfo {
             Integer sampleRate = trackJson.getInteger("sample_rate");
             Integer height = trackJson.getInteger("height");
             Integer width = trackJson.getInteger("height");
+            Integer fps = trackJson.getInteger("fps");
+            Integer loss = trackJson.getInteger("loss");
+            Integer frames = trackJson.getInteger("frames");
+            Long keyFrames = trackJson.getLongValue("key_frames");
+            Integer gop_interval_ms = trackJson.getInteger("gop_interval_ms");
+            Long gop_size = trackJson.getLongValue("gop_size");
+
             Long duration = trackJson.getLongValue("duration");
             if (channels != null) {
                 mediaInfo.setAudioChannels(channels);
@@ -125,6 +137,12 @@ public class MediaInfo {
             if (width != null) {
                 mediaInfo.setWidth(width);
             }
+            if (fps != null) {
+                mediaInfo.setFps(fps);
+            }
+            if (loss != null) {
+                mediaInfo.setLoss(loss);
+            }
             if (duration > 0L) {
                 mediaInfo.setDuration(duration);
             }
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
index 6b1c1d135..87aa801ea 100755
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -118,15 +118,6 @@ public class ZLMHttpHookListener {
         }
     }
 
-    /**
-     * rtsp/rtmp流注册或注销时触发此事件;此事件对回复不敏感。
-     */
-//    @ResponseBody
-//    @PostMapping(value = "/on_stream_changed", produces = "application/json;charset=UTF-8")
-//    public HookResult onStreamChanged(@RequestBody JSONObject param) {
-//        System.out.println(11);
-//        return HookResult.SUCCESS();
-//    }
     /**
      * rtsp/rtmp流注册或注销时触发此事件;此事件对回复不敏感。
      */
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
index 075197565..7292c9bd2 100755
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
@@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.conf.exception.ControllerException;
 import com.genersoft.iot.vmp.conf.security.JwtUtils;
 import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
 import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
+import com.genersoft.iot.vmp.media.bean.MediaInfo;
 import com.genersoft.iot.vmp.media.bean.MediaServer;
 import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerChangeEvent;
 import com.genersoft.iot.vmp.media.service.IMediaServerService;
@@ -162,6 +163,20 @@ public class ServerController {
         mediaServerService.delete(mediaServer);
     }
 
+    @Operation(summary = "获取流信息", security = @SecurityRequirement(name = JwtUtils.HEADER))
+    @Parameter(name = "app", description = "应用名", required = true)
+    @Parameter(name = "stream", description = "流ID", required = true)
+    @Parameter(name = "mediaServerId", description = "流媒体ID", required = true)
+    @GetMapping(value = "/media_server/media_info")
+    @ResponseBody
+    public MediaInfo getMediaInfo(String app, String stream, String mediaServerId) {
+        MediaServer mediaServer = mediaServerService.getOne(mediaServerId);
+        if (mediaServer == null) {
+            throw new ControllerException(ErrorCode.ERROR100.getCode(), "流媒体不存在");
+        }
+        return mediaServerService.getMediaInfo(mediaServer, app, stream);
+    }
+
 
     @Operation(summary = "重启服务", security = @SecurityRequirement(name = JwtUtils.HEADER))
     @GetMapping(value = "/restart")
diff --git a/web_src/src/components/common/mediaInfo.vue b/web_src/src/components/common/mediaInfo.vue
new file mode 100644
index 000000000..b410ce398
--- /dev/null
+++ b/web_src/src/components/common/mediaInfo.vue
@@ -0,0 +1,98 @@
+<template>
+  <div id="mediaInfo" >
+    <el-button style="position: absolute; right: 1rem;" icon="el-icon-refresh-right" circle size="mini" @click="getMediaInfo"></el-button>
+    <el-descriptions size="mini" :column="3" title="概况">
+      <el-descriptions-item label="观看人数">{{ info.readerCount }}</el-descriptions-item>
+      <el-descriptions-item label="网络">{{ formatByteSpeed() }}</el-descriptions-item>
+      <el-descriptions-item label="持续时间">{{info.aliveSecond}}秒</el-descriptions-item>
+    </el-descriptions>
+    <div style="display: grid; grid-template-columns: 1fr 1fr">
+      <el-descriptions size="mini" v-if="info.videoCodec" :column="2" title="视频信息">
+        <el-descriptions-item label="编码">{{ info.videoCodec }}</el-descriptions-item>
+        <el-descriptions-item label="分辨率"
+        >{{ info.width }}x{{ info.height }}
+        </el-descriptions-item>
+        <el-descriptions-item label="FPS">{{ info.fps }}</el-descriptions-item>
+        <el-descriptions-item label="丢包率">{{ info.loss }}</el-descriptions-item>
+      </el-descriptions>
+      <el-descriptions size="mini" v-if="info.audioCodec" :column="2" title="音频信息">
+        <el-descriptions-item label="编码">
+          {{ info.audioCodec }}
+        </el-descriptions-item>
+        <el-descriptions-item label="采样率">{{ info.audioSampleRate }}</el-descriptions-item>
+      </el-descriptions>
+    </div>
+
+  </div>
+</template>
+
+<script>
+
+export default {
+  name: "mediaInfo",
+  props: [ 'app', 'stream', 'mediaServerId'],
+  components: {},
+  created() {
+    this.getMediaInfo()
+  },
+  data() {
+    return {
+      info: {}
+    };
+  },
+  methods: {
+    getMediaInfo: function () {
+      this.$axios({
+        method: 'get',
+        url: `/api/server/media_server/media_info`,
+        params: {
+          app: this.app,
+          stream: this.stream,
+          mediaServerId: this.mediaServerId,
+        }
+      }).then((res)=> {
+        console.log(res.data.data);
+        if (res.data.code === 0) {
+          this.info = res.data.data
+        }
+
+      }).catch((error)=> {
+
+        console.log(error);
+      });
+    },
+    formatByteSpeed: function (){
+      let bytesSpeed = this.info.bytesSpeed
+      let num = 1024.0 //byte
+      if (bytesSpeed < num) return bytesSpeed + ' B/S'
+      if (bytesSpeed < Math.pow(num, 2)) return (bytesSpeed / num).toFixed(2) + ' KB/S' //kb
+      if (bytesSpeed < Math.pow(num, 3))
+        return (bytesSpeed / Math.pow(num, 2)).toFixed(2) + ' MB/S' //M
+      if (bytesSpeed < Math.pow(num, 4))
+        return (bytesSpeed / Math.pow(num, 3)).toFixed(2) + ' G/S' //G
+      return (bytesSpeed / Math.pow(num, 4)).toFixed(2) + ' T/S' //T
+    },
+    formatAliveSecond: function (){
+      let aliveSecond = this.info.aliveSecond
+      const h = parseInt(aliveSecond.value / 3600)
+      const minute = parseInt((aliveSecond.value / 60) % 60)
+      const second = Math.ceil(aliveSecond.value % 60)
+
+      const hours = h < 10 ? '0' + h : h
+      const formatSecond = second > 59 ? 59 : second
+      return `${hours > 0 ? `${hours}小时` : ''}${minute < 10 ? '0' + minute : minute}分${
+        formatSecond < 10 ? '0' + formatSecond : formatSecond
+      }秒`
+    }
+  },
+};
+</script>
+<style>
+.channel-form {
+  display: grid;
+  background-color: #FFFFFF;
+  padding: 1rem 2rem 0 2rem;
+  grid-template-columns: 1fr 1fr 1fr;
+  gap: 1rem;
+}
+</style>
diff --git a/web_src/src/components/dialog/devicePlayer.vue b/web_src/src/components/dialog/devicePlayer.vue
index f02c2c9fd..97162b5f4 100755
--- a/web_src/src/components/dialog/devicePlayer.vue
+++ b/web_src/src/components/dialog/devicePlayer.vue
@@ -232,31 +232,7 @@
             </div>
           </el-tab-pane>
           <el-tab-pane label="编码信息" name="codec" v-loading="tracksLoading">
-            <p>
-              无法播放或者没有声音?&nbsp&nbsp&nbsp试一试&nbsp
-              <el-button size="mini" type="primary" v-if="!coverPlaying" @click="coverPlay">转码播放</el-button>
-              <el-button size="mini" type="danger" v-if="coverPlaying" @click="convertStopClick">停止转码</el-button>
-            </p>
-            <div class="trank">
-              <p v-if="tracksNotLoaded" style="text-align: center;padding-top: 3rem;">暂无数据</p>
-              <div v-for="(item, index) in tracks" style="width: 50%; float: left" loading>
-                <span>流 {{ index }}</span>
-                <div class="trankInfo" v-if="item.codec_type == 0">
-                  <p>格式: {{ item.codec_id_name }}</p>
-                  <p>类型: 视频</p>
-                  <p>分辨率: {{ item.width }} x {{ item.height }}</p>
-                  <p>帧率: {{ item.fps }}</p>
-                </div>
-                <div class="trankInfo" v-if="item.codec_type == 1">
-                  <p>格式: {{ item.codec_id_name }}</p>
-                  <p>类型: 音频</p>
-                  <p>采样位数: {{ item.sample_bit }}</p>
-                  <p>采样率: {{ item.sample_rate }}</p>
-                </div>
-              </div>
-
-            </div>
-
+            <mediaInfo :app="app" :stream="streamId" :mediaServerId="mediaServerId"></mediaInfo>
           </el-tab-pane>
           <el-tab-pane label="语音对讲" name="broadcast">
             <div style="padding: 0 10px">
@@ -293,12 +269,13 @@ import PtzCruising from "../common/ptzCruising.vue";
 import ptzScan from "../common/ptzScan.vue";
 import ptzWiper from "../common/ptzWiper.vue";
 import ptzSwitch from "../common/ptzSwitch.vue";
+import mediaInfo from "../common/mediaInfo.vue";
 
 export default {
   name: 'devicePlayer',
   props: {},
   components: {
-    PtzPreset,PtzCruising,ptzScan,ptzWiper,ptzSwitch,
+    PtzPreset,PtzCruising,ptzScan,ptzWiper,ptzSwitch,mediaInfo,
     LivePlayer, jessibucaPlayer, rtcPlayer,
   },
   computed: {
@@ -334,7 +311,6 @@ export default {
       ptzPresetId: '',
       app: '',
       mediaServerId: '',
-      convertKey: '',
       deviceId: '',
       channelId: '',
       tabActiveName: 'media',
@@ -353,7 +329,6 @@ export default {
       scanSpeed: 100,
       scanGroup: 0,
       tracks: [],
-      coverPlaying: false,
       tracksLoading: false,
       showPtz: true,
       showRrecord: true,
@@ -453,63 +428,6 @@ export default {
       }
       return this.videoUrl;
 
-    },
-    coverPlay: function () {
-      var that = this;
-      this.coverPlaying = true;
-      this.$refs[this.activePlayer].pause()
-      that.$axios({
-        method: 'post',
-        url: '/api/play/convert/' + that.streamId
-      }).then(function (res) {
-        if (res.data.code === 0) {
-          that.convertKey = res.data.key;
-          setTimeout(() => {
-            that.isLoging = false;
-            that.playFromStreamInfo(false, res.data.data);
-          }, 2000)
-        } else {
-          that.isLoging = false;
-          that.coverPlaying = false;
-          that.$message({
-            showClose: true,
-            message: '转码失败',
-            type: 'error'
-          });
-        }
-      }).catch(function (e) {
-        console.log(e)
-        that.coverPlaying = false;
-        that.$message({
-          showClose: true,
-          message: '播放错误',
-          type: 'error'
-        });
-      });
-    },
-    convertStopClick: function () {
-      this.convertStop(() => {
-        this.$refs[this.activePlayer].play(this.videoUrl)
-      });
-    },
-    convertStop: function (callback) {
-      var that = this;
-      that.$refs.videoPlayer.pause()
-      this.$axios({
-        method: 'post',
-        url: '/api/play/convertStop/' + this.convertKey
-      }).then(function (res) {
-        if (res.data.code == 0) {
-          console.log(res.data.msg)
-        } else {
-          console.error(res.data.msg)
-        }
-        if (callback) callback();
-      }).catch(function (e) {
-      });
-      that.coverPlaying = false;
-      that.convertKey = "";
-      // if (callback )callback();
     },
 
         playFromStreamInfo: function (realHasAudio, streamInfo) {
@@ -531,10 +449,6 @@ export default {
             this.videoUrl = '';
             this.coverPlaying = false;
             this.showVideoDialog = false;
-            if (this.convertKey != '') {
-              this.convertStop();
-            }
-            this.convertKey = ''
             this.stopBroadcast()
         },