云服务器免费试用

Ryzen的简单介绍

服务器知识 0 663

本文目录:

  • 1、CSS中,input添加padding-left:30px后被推长的问题。
  • 2、Linux命令: tail
  • 3、CSS,这两个文本框没有垂直对齐,怎么解决?谢谢。
  • 4、前端里面box-sizing:border-box作用是什么?
  • 5、vuepc电脑可以获取设备吗
  • 6、Linux命令:tar

CSS中,input添加padding-left:30px后被推长的问题。

最简单的解决办法就是不用padding-left,改用text-indent:

text-indent: 30px

(我上次回答你的问题时不就是这样的吗?你也不想想我为什么不用padding?)

原因:元素的实际宽度=width+border+padding,所以如果padding不为0,元素的实际宽度就会被拉宽了。而text-indent是段落前空位(就是写文章时每一段前面的空格),不会影响到元素的实际宽度。

Linux命令: tail

Linux中的tail命令用来显示文件的最后几行至标准输出中,默认tail命令打印其相应文件的最后10行,其作用正好与head命令相反。

tail [options] file..

tail命令常用options参数

-n:这里的K指的是行数,该选项表示输出最后K行,在此基础上,如果使用-n +K,则表示从文件的第K行开始输出。

-c:这里的K指的是字节数,该选项表示输出文件最后K个字节的内容,在此基础上,使用-c +K则表示从文件第K个字节开始输出。

-f:输出文件变化后新增加的数据。

-q:不显示处理信息。

tail命令常用实例

示例1:查看/etc/vimrc的文件内容

tail /etc/vimrc

示例2:查看文件最后几行内容

tail -n 2 /etc/vimrc

CSS,这两个文本框没有垂直对齐,怎么解决?谢谢。

你好,你的html这样的结构,默认就是自动水平对齐的。现在是您的css代码写的不正确才会导致两个input上下偏移。

你只需在  .textMoRen 和 .spanWenBenKuangZuHeRongQi 上分别加上 vertical-align: middle  即可对齐,具体效果如图

希望我的回答能够帮到您

前端里面box-sizing:border-box作用是什么?

把内边距和边框,都算在一个盒子模型内,总宽度内,如果没有这个,宽度=内边距+边框

vuepc电脑可以获取设备吗

VUE2实现录像(PC端)可拍照 下载 预览 选取指定摄像头和麦克风设备 源代码可直接使用 原创

2022-10-16 17:57:44

嗯呐FT 

码龄1年

关注

2022.10月份 谷歌是最新版本 使用vue2写

下面的这些代码可以在谷歌浏览器的本地(localhost)和https环境下执行。中间有大量的注释可查看,基本上看一遍就懂,前面的坑我基本都踩过了。

如果是http环境的话,我下面这些代码是执行不了的,因为我做了获取指定设备的功能,如果要http环境中使用,需要把获取指定设备的相关代码删掉才能用,而且需要去谷歌的这个地址配置一下才能用,最下面我会介绍怎么在http环境中用。

功能如下:

1.可获取多个摄像头设备并选择其一进行录制

2.录制的过程中拔掉摄像头监听结束录制

3.可在录制中进行拍照生成png图片 可预览 可下载

4.录制完成会生成一个有声音和画面的webm格式视频 可在线预览下载

5.录制的过程中计时(最小误差)

界面展示(界面我就做个小Demo 没有过多去弄好看点 重要是script部分)

先上代码 -- html部分

template

div class="cha-d6bf-9f9e-10b8-f216 publish"

div class="cha-9f9e-10b8-f216-d480 box"

div class="cha-10b8-f216-d480-818d videoPart"

div class="cha-f216-d480-818d-ddf2 videoRecord" @mouseenter="hoverVideo(0)" @mouseleave="hoverVideo(1)"

video id="videoCamera" :width="videoWidth" :height="videoHeight" autoPlay/video

div class="cha-0395-6937-304c-dd89 hoverVideoOutside" v-if="ifHoverVideo ifStartRecord"

div class="cha-6937-304c-dd89-6404 hoverVideoInside"

div class="cha-304c-dd89-6404-5d1c hoverVideoInsideInside"

div class="cha-dd89-6404-5d1c-a195 hoverVideoBtn"div class="cha-6404-5d1c-a195-19ab hoverVideoBtnInside"/div/div

span{{recordHMSTime}}/span

/div

/div

/div

/div

canvas id="canvasCamera" class="cha-5d1c-a195-19ab-f7cc canvas" :width="videoWidth" :height="videoHeight"/canvas

video v-if="showVideo" :src="videoSrc" autoplay controls/video

img v-if="showImg" class="cha-a195-19ab-f7cc-7d79 imgClass" :src="imgSrc" alt=""

/div

div

el-select v-model="deviceId" placeholder="请选择摄像头" @change="selectVideoChange" @focus="findVideoDevice" :disabled="ifStartRecord"

el-option

v-for="item in deviceArr"

:key="item.deviceId"

:label="item.label"

:value="item.deviceId"

/el-option

/el-select

el-button v-if="!ifStartRecord" @click="startRecord" icon="el-icon-video-camera" size="small"开始录制/el-button

el-button v-else @click="stopRecord" icon="el-icon-switch-button" size="small"结束录制/el-button

el-button @click="photographBtn" icon="el-icon-camera" size="small"拍照/el-button

/div

vxe-table

border

resizable

show-overflow

ref="xTable"

height="500"

:row-config="{isHover: true}"

:data="tableData"

vxe-column type="seq" width="60"/vxe-column

vxe-column field="name" title="Name"/vxe-column

vxe-column title="操作" width="200" show-overflow

template #default="{ row }"

vxe-button type="text" icon="vxe-icon-edit" @click="preview(row)"预览/vxe-button

vxe-button type="text" icon="vxe-icon-edit" @click="download(row)"下载/vxe-button

/template

/vxe-column

/vxe-table

/div

/div

/template

CSS代码

style scoped

.canvas{

opacity: 0!important;

}

.videoPart{

position: relative;

display: flex;

align-items: center;

}

.hoverVideoOutside{

position: absolute;

top: 0px;

left: 0px;

width: 500px;

height: 300px;

background:linear-gradient(#000,transparent 20%);

z-index: 999;

}

.hoverVideoInside{

position: relative;

width: 100%;

height: 100%;

}

.hoverVideoInsideInside{

position: absolute;

top: 10px;

left: 380px;

padding: 2px;

display: flex;

justify-content: center;

align-items: center;

}

.hoverVideoBtn{

width: 30px;

height: 30px;

border-radius: 50%;

border: 2px solid red;

padding: 3px;

box-sizing: border-box;

margin-right: 4px;

}

.hoverVideoBtnInside{

background: red;

width: 20px;

height: 20px;

border-radius: 50%;

box-sizing: 50%;

}

span{

color: #fff;

}

.videoRecord{

position: relative;

}

.imgClass{

width: 500px;

height: 300px;

}

/style

逻辑部分

script

export default {

name: 'HelloWorld',

data() {

return {

ifOpenCamera: false,//控制摄像头开关

ifStartRecord:false, //是否开始录制

thisVideo: null,

thisContext: null, //canvas

thisCanvas: null,

videoWidth: 500,

videoHeight: 300,

videoCecorded: [], //接受的数据流

mediaRecorderData: {},

videoSrc:'', //录制完的视频预览

imgSrc:'',//录制完预览的图片地址

deviceArr:[],//获取该电脑的摄像头

deviceId:'', //选择哪个摄像头

tableData:[], //录制完 制作表格数据

showVideo:false, //录制完预览视频

showImg:false,//录制完预览图片

recordTime:0, //监听录像的时间

recordHMSTime:'00:00:00', //监听录像的时间

ifHoverVideo:false, //监听是否鼠标在视频的上面 显示录制时间

timer:null, //每一秒执行一次计算录像的时间 这个是有误差的

startTime:'', //记录开始录制的时间戳

stream:null,

}

},

created() {

this.initDevice();

},

methods: {

initDevice(){

this.$nextTick(() = {

this.videoCecorded = []

this.mediaRecorderData = null

this.thisCanvas = document.getElementById('canvasCamera');

this.thisContext = this.thisCanvas.getContext('2d');

this.thisVideo = document.getElementById('videoCamera');

// 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象

console.log('navigator.mediaDevices', navigator.mediaDevices)

if (navigator.mediaDevices === undefined) {

navigator.mediaDevices = {}

this.dialogVisible = !this.dialogVisible;

console.log('http环境下没开那个谷歌权限 所以有点问题 得弹出提示弹窗 如果是本地或者https环境就基本不会走到这里')

this.$message({

message: '去谷歌浏览器配置网址',

type: 'error'

})

}

// 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象

// 使用getUserMedia,因为它会覆盖现有的属性。

// 这里,如果缺少getUserMedia属性,就添加它。

if (navigator.mediaDevices.getUserMedia === undefined) {

navigator.mediaDevices.getUserMedia = function (constraints) {

// 首先获取现存的getUserMedia(如果存在)

let getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.getUserMedia;

// 有些浏览器不支持,会返回错误信息

// 保持接口一致

if (!getUserMedia) {

return Promise.reject(new Error('getUserMedia is not implemented in this browser'))

}

// 否则,使用Promise将调用包装到旧的navigator.getUserMedia

return new Promise(function (resolve, reject) {

getUserMedia.call(navigator, constraints, resolve, reject)

})

}

}

this.findVideoDevice()

})

},

// 每次点开下拉框的时候都要去获取现在有多少个设备 以防在打开这个网站之后把摄像头拔了等情况

async findVideoDevice(){

this.deviceId = ''

this.deviceArr = []

const _this = this

try{

// 获取你电脑中有什么设备

let deviceArr = await navigator.mediaDevices.enumerateDevices();

if(this.deviceArr.length == 0){

this.$message({

message: '没有摄像头设备',

type: 'error'

})

this.deviceArr = []

return

}

console.log('设备',deviceArr)

deviceArr.forEach(item={

if(item.kind == 'videoinput'){

this.deviceArr.push(item) //获取你电脑中有多少个摄像头设备

}

})

}catch(error){

console.log(error)

this.deviceArr = []

}

},

// 选择完是哪个摄像头以后执行的方法

selectVideoChange(){

this.$nextTick(() = {

const _this = this;

const constraints = {

audio: true,

video: {

width: _this.videoWidth,

height: _this.videoHeight,

transform: 'scaleX(-1)',

deviceId:{exact:this.deviceId}

},

};

navigator.mediaDevices.getUserMedia(constraints).then(async(stream)={

// 旧的浏览器可能没有srcObject

if ('srcObject' in _this.thisVideo) {

_this.thisVideo.srcObject = stream

} else {

// 避免在新的浏览器中使用它,因为它正在被弃用。

_this.thisVideo.src = window.URL window.URL.createObjectURL(stream)

}

_this.thisVideo.onloadedmetadata = function (e) {

_this.thisVideo.play()

}

_this.ifOpenCamera = true

}).catch(err = {

this.errReponse(err)

});

});

},

// 开始录制

startRecord() {

if(this.deviceId == ''){

this.$message({

message: '请选择摄像头',

type: 'error'

})

return

}

const _this = this

this.mediaRecorderData = null

this.videoCecorded = []

this.$nextTick(()={

const constraints = {

audio: true,

video: {

width: this.videoWidth,

height: this.videoHeight,

transform: 'scaleX(-1)',

deviceId:{exact:this.deviceId} //选取指定的设备来录制

},

};

//必须在model中render后才可获取到dom节点,直接获取无法获取到model中的dom节点

navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {

_this.stream = stream

// 这个要重写一次

// 我插第三方的视频录像设备的情况下 点击录像 然后把设备拔出来 这个时候画面是黑色的

// 如果没有重写下面的方法 插进设备后 点击录像 画面依然是黑色的 但是能录像 只是界面上不显示

if ('srcObject' in _this.thisVideo) {

_this.thisVideo.srcObject = stream

} else {

// 避免在新的浏览器中使用它,因为它正在被弃用。

_this.thisVideo.src = window.URL window.URL.createObjectURL(stream)

}

_this.thisVideo.onloadedmetadata = function (e) {

_this.ifOpenCamera = true

_this.thisVideo.play()

}

_this.startRecording(stream);//调用录制控件方法,触发开始录制

}).catch(err = {

// 点录制之前断开设备连接 但选择框已经选了设备 就会触发这个err

this.errReponse(err)

});

})

},

//拍照按钮

photographBtn() {

//先判断是否开启了摄像头

if(!this.ifOpenCamera){

this.$message({

message: '摄像头都还没开呢 傻猪猪',

type: 'error'

})

return

}

// 点击,canvas画图

this.thisContext.drawImage(this.thisVideo, 0, 0, this.videoWidth, this.videoHeight);

// 如果图片尺寸不想 500 300 那就写下面这个

// this.thisContext.drawImage(this.thisVideo, 0, 0, this.videoWidth, this.videoHeight,0,0,1000, 600);

const fileName = (new Date).toISOString().replace(/:|\./g,'-')

const a = this.thisCanvas.toDataURL('image/png')

const file = this.dataURLtoFile(a,fileName + 'png')

this.tableData.push({

id:2,

name:fileName + 'png',

url:this.thisCanvas.toDataURL('image/png'),

type:'png'

})

},

//停止录制

stopRecord() {

if (this.thisVideo this.thisVideo !== null) {

this.mediaRecorderData.stop(); //结束录制

}

},

// 开始录制中

startRecording(stream) {

console.log('stream 在开始的时候的',stream)

let _this = this

this.mediaRecorderData = new MediaRecorder(stream, {

mimeType: 'video/webm;codecs=vp8,opus' //不加这个codecs=vp8,opus有时候下载下来之后看几秒就没了 残缺的视频

});

this.mediaRecorderData.addEventListener("dataavailable", (e) = {

if (e.data.size 0) {

_this.videoCecorded.push(e.data);//视频录制视频流数据

};

});

this.mediaRecorderData.addEventListener("stop", () = {

console.log("结束录制");

_this.updataVideo();//上传实时录制的视频

_this.ifStartRecord = false

_this.recordTime = 0

_this.recordHMSTime = '00:00:00'

clearTimeout(_this.timer)

_this.timer = null

});

this.mediaRecorderData.addEventListener("start", (e) = {

console.log("开始 录制");

_this.ifStartRecord = true

_this.recordTime = 0

_this.startTime = new Date().getTime();

_this.timer = setTimeout(_this.fixed,1000)

});

this.mediaRecorderData.start()

},

// 上传录制视频方法,获取视频地址

updataVideo() {

const blob = new Blob(this.videoCecorded, {

type: 'video/webm'

});

const fileName = (new Date).toISOString().replace(/:|\./g,'-')

this.tableData.push({

id:2,

type:'webm',

name:fileName + '.webm',

url:URL.createObjectURL(blob)

})

},

// 预览视频 图片

preview(row){

if(row.type == 'png'){

this.showImg = true

this.showVideo = false

this.imgSrc = row.url

}else if(row.type == 'webm'){

this.showVideo = true

this.showImg = false

this.videoSrc = row.url

}else{

this.$message({

message: '无法预览',

type: 'error'

})

}

},

download(row){

let aTag = document.createElement('a');//创建一个a标签

aTag.download = row.name;

aTag.href = row.url;

aTag.click();

},

hoverVideo(num){

if(num){

// 移出

this.ifHoverVideo = false

}else{

// 移入

this.ifHoverVideo = true

}

},

secondChangeMinute(second){

const hour = parseInt(second / 3600)

const min = parseInt(second / 60)

const se = parseInt(second % 60)

const cHour = hour10?'0'+hour:hour

const cMin = min10?'0'+min:min

const cSe = se10?'0'+se:se

return cHour + ':' + cMin + ':' + cSe

},

fixed(){

this.recordTime += 1

this.recordHMSTime = this.secondChangeMinute(this.recordTime)

if(!this.stream.active){

this.stopRecord()

}

var offset = new Date().getTime() - (this.startTime + this.recordTime * 1000);

var nextTime = 1000 - offset;

if (nextTime 0) nextTime = 0;

this.timer = setTimeout(this.fixed, nextTime);

},

errReponse(err){

const message = err.message || err

const response = {

'permission denied': '浏览器禁止本页面使用摄像头或麦克风,请开启相关的权限',

'requested device not found': '未检测到摄像头'

}

console.log(response[ message.toLowerCase() ] || '未知错误');

this.$message({

message: response[ message.toLowerCase() ] || '未知错误',

type: 'warning'

})

},

dataURLtoFile: function(dataurl, filename) {

let arr = dataurl.split(','),

mime = arr[0].match(/:(.*?);/)[1],

bstr = atob(arr[1]),

n = bstr.length,

u8arr = new Uint8Array(n);

while (n--) {

u8arr[n] = bstr.charCodeAt(n);

}

return new File([u8arr], filename, { type: mime });

},

// 这个方法是给需要的人看的 演示打开摄像头的方法

async openCamera(){

await navigator.mediaDevices.getUserMedia({audio:true,video:true}).then(()={

//我这个时候已经打开摄像头了

}).catch(err={

this.errReponse(err)

})

},

// 这个方法是给需要的人看的 演示关闭摄像头的方法

closeCamera(){

this.thisVideo.srcObject.getTracks().forEach(item = {

// 关闭当前所有已打开的设备(你刚刚选择的摄像头设备和你默认的麦克风)

item.stop()

})

},

}

}

/script

问题解答区域:

1.录制的视频只能是webm格式吗?进度条呢?

答:我在写程序的时候发现只能写webm格式,如果是写MP4或者其他类型,视频下载下来是没有办法播放的,可能在移动端就没有问题,我还没有去尝试在移动端做这个功能。webm格式我所知道的有两个弊端,下载下来的时候无法拖动进度条,而且要在指定播放器中才能播放。如果想要解决这个进度条的问题,可以去看这个地址的解决方法。前端 mediaRecorder 录制视频源代码实例,和本地播放器无法定位进度条问题分析和解决_anne都的博客-CSDN博客_mediarecorder 进度条

2.http问题

答:在http环境下是可以录制的,但是我上面的代码运行不了就是了。因为我添加了一个获取用户电脑中设备的功能,该功能在http环境下没有办法获取,可能是浏览器出于安全的问题。如果想要在http环境下录制,可以参考下面的这个地址,我也是百度了很久,看了很多别人的博客才得出的最终代码结果。地址如下:

=1.JS调用媒体设备失败 --- getUserMedia undefine 问题(各浏览器配置方法)_!--玄德--的博客-CSDN博客_浏览器不支持getusermedia

=2.

PC端调用摄像头录制视频——vue标准写法_前端_森森的博客-CSDN博客_vue调用摄像头录像

=3.

JS基于页面实现音视频的录制(一)_画虎成鳖的博客-CSDN博客_js录制视频

3.表格不一定要用vxetable,随便用

4.如果还有什么问题再在评论区问吧。。

Linux命令:tar

原单词 tar命令最初的设计目的是将文件备份到磁带上(tape archive),因而得名tar

实物长这样

tar 命令是linux系统中常用的 压缩文件 和 解压缩文件命令

tar 命令的参数 异常之多,咱们只学习满足 压缩文件 和 解压缩文件 命令的参数就可以了

mark 工作中应用于安装软件,搭建应用,部署环境/mark

举例: 将root目录下的 adir目录和a.txt文件 压缩为 test.tar.gz

注意是大写C

如果 不使用-C参数 则默认解压至当前工作目录

举例: 将 test.tar.gz 压缩文件解压到/root目录

-c 建立新的备份文件。

-x 从备份文件中还原文件。

-v 显示指令执行过程。

-f 指定备份文件。

-z 通过gzip指令处理备份文件。(如果解压文件后缀是.tar,没有.gz则不需要使用-z参数)

-C 指定解压到的目录

使用xshell连接linux

在root 目录下 新建 tarTest目录

进入tarTest目录

压缩 /root/lnTest文件夹 和 /root/Centos-7.repo 文件 到 /root/tarTest目录下,压缩文件名为 test.tar.gz

进入/root/tarTest目录

解压test.tar.gz到当前目录(/root/tarTest)

解压test.tar.gz到/root/rmTest目录

【Ryzen】的内容来源于互联网,如引用不当,请联系我们修改。

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942@qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: Ryzen的简单介绍
本文地址: https://solustack.com/12449.html

相关推荐:

网友留言:

我要评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。