nodejs与前端js大文件、切片、视频流相关技术示例

这篇具有很好参考价值的文章主要介绍了nodejs与前端js大文件、切片、视频流相关技术示例。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

nodejs服务代码

const express = require("express");
const fs = require("fs");

const app = express();
// 展示html页面
app.get("/", function (req, res) {
    res.sendFile(__dirname + "/index.html");
});

// nodejs切片读取文件示例
if (!Date.now()) {
    let i = 0
    const readableStream = fs.createReadStream('asai.mp4') + fs.createReadStream('asai1.mp4');
    readableStream.on('data', (chunk) => {
        i++
        console.log(666.123465, i, chunk);
    });
    readableStream.on('end', () => {
        console.log('数据读取完毕');
    });
}

// nodejs合并切片示例
// 方案一
if (!Date.now()) {
    const writeStream = fs.createWriteStream('asai-a.mp4');
    let readStream
    function concatFiles(readfiles) {
        if (readfiles && readfiles[0]) {
            console.log(666.30002, readfiles[0])
            readStream = fs.createReadStream(readfiles[0]);
            readStream.pipe(writeStream, { end: false })
            readStream.on('end', () => {
                readfiles.shift()
                concatFiles(readfiles);
            });
        } else {
            writeStream.close();
        }
        readStream.on('error', (error) => { // 监听错误事件,关闭可写流,防止内存泄漏
            console.error(666.789, error);
            writeStream.close();
        });
    }
    concatFiles(['asai.mp4', 'asai1.mp4'])
}

// 方案二
if (!Date.now()) {
    // 读取一个文件,使用fs读取文件获取一个Buffer类型数据
    const buffer = fs.readFileSync('asai.mp4')
    // 将文件进行切分
    const file1 = buffer.subarray(0, 3000000)
    const file2 = buffer.subarray(3000000)
    // 全并多个切片文件
    const allfile = Buffer.concat([file1, file2])
    console.log(666.2008, allfile)

    // 读取文件切片
    const s1 = fs.readFileSync('asai.mp4')
    const s2 = fs.readFileSync('asai1.mp4')
    // 将读取的文件切片合并
    const bb = Buffer.concat([s1, s2])
    // 将合并的切片数据,写到一个新文件中
    fs.writeFileSync('asai-c.mp4', bb)
}

// 多视频切片发送示例(咱不支持)
const videoData = {
    list: [
        // { path: 'asai1.mp4', size: fs.statSync('asai1.mp4').size },
        { path: 'asai.mp4', size: fs.statSync('asai.mp4').size },
    ],
    index: 0,
    curStart: 0,
    curSize: 0,
    totalSize: 0
}
videoData.totalSize = videoData.list.reduce((prev, cur) => {
    return prev + cur.size
}, 0)


app.get("/video", function (req, res) {
    const range = req.headers.range;
    if (range) {
        resVideo(res, range)
    } else {
        const path = 'asai.mp4'
        const fileSize = fs.statSync(path).size
        let head = {
            'Content-Length': fileSize,
            'Content-Type': 'video/mp4',
        };
        res.writeHead(200, head);
        fs.createReadStream(path).pipe(res);
        res.status(400).send("Requires Range header");
    }
});

app.listen(8000, function () {
    console.log("Listening on port 8000!");
});

function resVideo(res, range) {
    console.log(666.10001, range)
    let [, start, end] = range.match(/(\d*)-(\d*)/);
    if (videoData.list[videoData.index]) {
        // if (start < videoData.curSize) {
        //     start = videoData.curSize
        // }
        // range = 'bytes=1458753-';
        // 保证request的header里面有range,没有range就无法判断需要把哪一部分content写入response
        // const videoPath = "asai.mp4";
        const videoPath = videoData.list[videoData.index].path;
        const videoSize = videoData.list[videoData.index].size;
        // 还需要资源的路径和资源的大小,资源的大小会用来计算哪一部分content要被send
        const CHUNK_SIZE = 10 ** 5; // 10 ** 6 ≈ 1MB
        // const start = Number(range.replace(/\D/g, "")); // 截取开始位置

        // 这里规定每次返回1M的内容,开始位置从request的header里获取并将其转成Number类型
        end = Math.min(end ? end : start + CHUNK_SIZE, videoData.curStart + videoSize - 1); // 截取结束位置


        console.log(666.10002, videoPath, { start, end, size: videoData.totalSize, startv: start - videoData.curStart, endv: end - videoData.curStart, sizev: videoSize }, (start >= videoData.curStart && start < end), videoData)

        // 这里需要使用fs来创建一个videoSteam,使用videoPath和start和end作为参数
        const videoStream = fs.createReadStream(videoPath, { start: start - videoData.curStart, end: end - videoData.curStart });

        // const newRange = `bytes ${start}-${end}/*`
        // const newRange = `bytes ${start}-${end}/1509200`
        // const newRange = `bytes ${start}-${end}/${videoSize}`
        const newRange = `bytes ${start}-${end}/${videoData.totalSize}`


        // 视频发送状态
        console.log(666.789, newRange)

        // 在响应头里面我们需要返回Content的大小,Content-range,Accept-ranges,Content-type。
        const headers = {
            "If-Range": "Etag",
            "Content-Range": newRange,
            "Accept-Ranges": "bytes",
            "Content-Type": "multipart/byteranges",
            // "Content-Type": "video/mp4",
            // "Content-Length": CHUNK_SIZE,
            "Transfer-Encoding": "chunked",// 假如不知道内容长度,代替Content-Length
        };


        // 状态码设置为206表明我们返回的是部分内容。
        res.writeHead(206, headers);


        // 把videoStream pipe到response即可
        videoStream.pipe(res);

        // 手工记录cursize
        videoData.curSize = end

        if (end - videoData.curStart === videoSize - 1 && videoData.list[videoData.index + 1]) {
            videoData.curStart += videoData.list[videoData.index].size
            videoData.index += 1
            console.log(666.123, videoPath, 'send over.', videoData)
        }
    }
}

前端html页面

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>视频/文件切片请求处理nodejs+html</title>
  <style>
    body {
      max-width: 100%;
      height: 100vh;
      background-color: rgb(14, 14, 14);
      display: flex;
      margin: auto;
      align-items: center;
      justify-content: center;
    }
  </style>
</head>

<body>
  <video height="100%" src="/video" controls autoplay muted></video>
</body>

</html>

附件:前端js切片上次

<html lang="zh-cn">

<head>
    <meta title="文件切片合并" />
</head>

<body>
    <!-- 页面选择文件 -->
    <input type="file" id="file" />
    <!-- 将加载的视频文件进行切片后合并,并播放 -->
    <video id="play" controls style="width:500px;height:auto"></video>
</body>
<script>
    file.addEventListener('change', async (e) => {
        // 获取FileList中的File文件
        let file2 = file.files[0]

        // ----------第一种方式-------------------
        // 使用Blob的slice方法切片,使用Blob构造函数进行数据合并
        // 将加载的文件进行切片
        // let s1 = file2.slice(0,100)
        // let s2 = file2.slice(100)

        // 将切片的文件进行数据合并
        // let newFile = new Blob([s1,s2])


        // -----------第二种方式------------------
        // 如何对大文件进行流式读取
        let chunckArr = []

        // 通过Blob获取 ReadableStream 流对象,再获取可读的流读取器
        let reader = file2.stream().getReader()
        let done = false
        while (!done) {
            // 使用流读取器的read方法,获取流队列中的下一个分块数据
            let { value, done: readDone } = await reader.read()
            console.log(value)
            chunckArr.push(value)
            done = readDone
        }
        // 通过Blob构造函数合并流数据
        let newFile = new Blob(chunckArr)

        // 进行页面播放
        play.setAttribute('src', URL.createObjectURL(newFile))
    })

</script>

</html>

文章来源地址https://www.toymoban.com/news/detail-654709.html

到了这里,关于nodejs与前端js大文件、切片、视频流相关技术示例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 前端播放大视频卡顿的解决(m3u8视频流)

    前端播放大视频卡顿的解决(m3u8视频流)

    最近在一个大屏看板项目中有一个需求是:要求视频和看板要进行来回切换。 最开始的做法是将MP4视频放在项目里,在本地运行时是没什么问题的,但是在往仓库里提交代码时出现了问题。当单个文件超过100MB时会导致代码提交失败; 后来的解决方案是将视频文件放到服务器

    2024年01月19日
    浏览(9)
  • Vue实现摄像头视频分屏, 使用flv.js接收rtmp/flv视频流

    Vue实现摄像头视频分屏, 使用flv.js接收rtmp/flv视频流

    1. 现有的平台系统播放实时视频。 因为用户电脑都是Linux系统,无法直接使用海康前端SDK,讨论决定由后台推视频流,简单调研后发现最流行的是flv,而且有B站开源的flv.js适配。前期后台推给我RTMP前缀的视频流,我尝试使用video.js,西瓜视频等都失败了,后来后端改为http前

    2024年02月03日
    浏览(11)
  • vue2使用rtsp视频流接入海康威视摄像头(纯前端)

    vue2使用rtsp视频流接入海康威视摄像头(纯前端)

    海康威视官方的RTSP最新取流格式如下: rtsp://用户名:密码@IP:554/Streaming/Channels/101 用户名和密码 IP就是登陆摄像头时候的IP(笔者这里IP是192.168.1.210) 所以笔者的rtsp流地址就是 rtsp://用户名:密码@192.168.1.210:554/Streaming/Channels/101 1.1关闭 萤石云的接入 1.2 调整视频编码为H.264 在此下载

    2024年04月26日
    浏览(6)
  • 前端实现H265编码的m3u8视频流播放

    前端实现H265编码的m3u8视频流播放

    前言 视频监控是智慧城市、智慧园区等WebGIS类系统中最为常见的硬件对接设备,最常用的监控视频流格式为m3u8格式,但是m3u8格式通常都是h.265编码格式的,我搜遍了几乎所有前端视频播放插件,几乎普通的播放器插件都不支持h.265格式的视频编码。本文就带领大家了解H265视

    2024年01月18日
    浏览(6)
  • 前端VUE播放RTSP、RTMP、HLS、FLV视频流的解决方案

    前端VUE播放RTSP、RTMP、HLS、FLV视频流的解决方案

    最近有个需求是前端在浏览器显示摄像头传回的RTSP视频流,我和后端都没做过视频流的项目,所以一步步摸索过来,方法和经验供大家参考。前端采用的技术有VUE+video.js+flv.js 从上图可以看出,RTSP流不能直接在浏览器播放,所以需要转码: RTMP的流需要在浏览器中用flash播放

    2024年02月06日
    浏览(10)
  • Qt推流程序自动生成网页远程查看实时视频流(视频文件/视频流/摄像头/桌面转成流媒体rtmp+hls+webrtc)

    Qt推流程序自动生成网页远程查看实时视频流(视频文件/视频流/摄像头/桌面转成流媒体rtmp+hls+webrtc)

    推流程序将视频流推送到流媒体服务器后,此时就等待验证拉流播放,一般可以选择ffplay命令行播放或者vlc等播放器打开播放,也可以选择网页直接打开拉流地址播放,一般主流的浏览器都支持网页直接播放hls/m3u8/webrtc类型的视频流,而且推流的主要目的可能就是为了能够在

    2024年02月05日
    浏览(33)
  • 计算机网络文件拆分—视频流加载、断点续传

    视频流加载的原理是通过网络传输和播放器解码来实现的。 首先, 视频文件会被分成一系列小的数据包 ,通常是以流的形式传输,这些数据包通过网络传输到用户设备。在传输过程中,可以采用各种协议,如HTTP、RTSP等。 一旦数据包到达用户设备,播放器会开始接收并解码

    2024年02月10日
    浏览(5)
  • Windows上搭建Nginx-http-flv实现rtsp视频流推流到rtmp流媒体服务器并转换和前端拉取http-flv视频流

    Windows上搭建Nginx-http-flv实现rtsp视频流推流到rtmp流媒体服务器并转换和前端拉取http-flv视频流

    Nginx-http-flv-module流媒体服务器搭建+模拟推流+flv.js在前端html和Vue中播放HTTP-FLV视频流: Nginx-http-flv-module流媒体服务器搭建+模拟推流+flv.js在前端html和Vue中播放HTTP-FLV视频流_霸道流氓气质的博客-CSDN博客 Windows上搭建Nginx RTMP服务器并使用FFmpeg实现本地视频推流: Vue中使用vue-vi

    2024年02月15日
    浏览(6)
  • 视频爬虫:解析m3u8文件 python m3u8库,m3u8文件中.ts视频流的解密下载

    视频爬虫:解析m3u8文件 python m3u8库,m3u8文件中.ts视频流的解密下载

    这里需要引用的库是: from Crypto.Cipher import AES 有坑哈, python3.0 之后直接安装crypto你会发现不管怎么着都会报错。 经过查找资料找到了原因,原来是20年之后crypto已经被pycryptohome替换掉啦, 如果之前安装过crypyo 活pycrypto需要先卸载 然后再安装 pycryptohome 就可以啦 首先我们需

    2024年02月14日
    浏览(13)
  • Qt推流程序(视频文件/视频流/摄像头/桌面转成流媒体rtmp+hls+webrtc)可在网页和播放器远程观看

    Qt推流程序(视频文件/视频流/摄像头/桌面转成流媒体rtmp+hls+webrtc)可在网页和播放器远程观看

    推流直播就是把采集阶段封包好的内容传输到服务器的过程。其实就是将现场的视频信号从手机端,电脑端,摄影机端打包传到服务器的过程。“推流”对网络要求比较高,如果网络不稳定,直播效果就会很差,观众观看直播时就会发生卡顿等现象,观看体验比较糟糕。主流

    2024年02月04日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包