下载知乎视频并在线播放

项目地址

下载知乎视频

知乎的视频使用HLS实时流传输协议进行传输.HLS,Http Live Streaming 是由Apple公司定义的用于实时流传输的协议,HLS基于HTTP协议实现,传输内容包括两部分,一是M3U8描述文件,二是TS媒体文件。

1、M3U8文件

用文本方式对媒体文件进行描述,由一系列标签组成。

#EXTM3U#EXT-X-TARGETDURATION:5#EXTINF:5,./0.ts#EXTINF:5,./1.ts#EXTM3U:每个M3U8文件第一行必须是这个tag。#EXT-X-TARGETDURATION:指定最大的媒体段时间长度(秒),#EXTINF中指定的时间长度必须小于或等于这个最大值。该值只能出现一次。#EXTINF:描述单个媒体文件的长度。后面为媒体文件,如./0.ts

2、ts文件

​ ts文件为传输流文件,视频编码主要格式h264/mpeg4,音频为acc/MP3。

获取答案中的视频链接

知乎视频链接的格式https://www.zhihu.com/video/984740889473818624

  1. 访问答案链接,获取链接对应的html文件内容

    import request from 'request-promise'
    import unescape from 'unescape'
    const TARGET_VIDEO_DIR = `${__dirname}/public/video`
  2. 使用正则表达式获取视频链接

    const rex = />(https:\/\/www.zhihu.com\/video\/([0-9]+))</
    const matchResult = content.match(rex)
    if (!matchResult) {throw new Error('there is not video exist')
    }
    // https://www.zhihu.com/video/984740889473818624
    const videoUrl = matchResult[1]
    // 984740889473818624
    const videoHash = matchResult[2]

下载视频链接中对应的m3u8和ts文件

​ 访问获取到的视频链接https://www.zhihu.com/video/984740889473818624, 使用F12查看具体的访问过程,可以发现,知乎对此视频链接的处理如下:

  1. 请求https://lens.zhihu.com/api/videos/984740889473818624,获取播放列表,结果如下:

    {
    "playlist":{
    "ld":{"width": 640, "format": "m3u8", "play_url": "https://vdn.vzuu.com/Act-ss-m3u8-ld/4d2f1b27a0a0417c937af38548310006/135ba0d0-62e7-11e8-8574-0242ac112a1f.m3u8?auth_key=1534147563-0-0-bb23f2e6455b894f0aa1d216afbc0a12&expiration=1534147563&disable_local_cache=0",…},
    "hd":{"width": 1280, "format": "m3u8", "play_url": "https://vdn.vzuu.com/Act-ss-m3u8-hd/4d2f1b27a0a0417c937af38548310006/135ba0d0-62e7-11e8-8574-0242ac112a1f.m3u8?auth_key=1534147563-0-0-a0797a8a37c6b316ece393d89a213978&expiration=1534147563&disable_local_cache=0",…},
    "sd":{"width": 848, "format": "m3u8", "play_url": "https://vdn.vzuu.com/Act-ss-m3u8-sd/4d2f1b27a0a0417c937af38548310006/135ba0d0-62e7-11e8-8574-0242ac112a1f.m3u8?auth_key=1534147563-0-0-d92ae153e7730835c684202afa3da9d8&expiration=1534147563&disable_local_cache=0",…}
    },
    "title": "",
    "duration": 19,
    "cover_info":{
    "width": 1280,
    "thumbnail": "https://pic3.zhimg.com/80/v2-73bb3006d2228ce55d6aade8975e0ade_b.jpg",
    "height": 2258
    },
    "type": "video",
    "id": "984740889473818624",
    "misc_info":{}
    }
  2. 选择playlist中的某一个列别,使用play_url下载所有ts文件病进行播放

根据以上的步骤,编写实现代码

  1. 调用https://lens.zhihu.com/api/videos/984740889473818624获取play_url

    const vidoesApi = `https://lens.zhihu.com/api/videos/${videoHash}`
    // get m3u8 url, just need to get one, and tsFetcher will download all ts files
    const m3u8Url = JSON.parse(await request(vidoesApi)).playlist.hd.play_url
  2. 从play_url下载所有TS文件(使用download-m3u8依赖完成下载)

    shell
    npm install -g download-m3u8
    # simply pass a http link to a m3u8 playlist
    download-m3u8 https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8

    为了能在程序中自动下载使用child_process中的execSync完成shell命令的调用

    typescript
    import { execSync } from 'child_process'
    execSync(`download-m3u8 ${m3u8Url}`)
    console.log('download all ts files done.')

    至此,所有的ts相关的文件都会保存在./{http-host}/{filename}

将所有的ts 文件合并成一个大的ts文件

ts文件是以二进制的格式进行存储, 可以以二进制合并的方式直接将所有小的ts文件合并成一个大的ts文件,在linux系统下可以使用cat命令直接完成.

// Get all ts file
const tsFiles = fs.readdirSync(videoDir).filter((value) => {return 'ts' === value.split('.')[1]
})
const sourceFiles = tsFiles.join(' ')
execSync(`cat ${sourceFiles} > ${videoDir}/${name}.ts`)
console.log('merge ts files done.')

将ts文件转成MP4格式的视频文件

将ts文件转换成mp4的工作可以使用mpegts_to_mp4依赖包完成

import mpegts_to_mp4 from 'mpegts_to_mp4'
mpegts_to_mp4(tsFileName, 'test.mp4', async (err) => {if(err){console.log("Error: "+err)}// remove all ts filesconst downloadRootDir = path.join(videoDir, '../', '../')await rimraf_then(downloadRootDir)console.log("Done converting vids.")
})

html5和Nodejs使用视频流在线播放

基本知识

HTTP status 206(Partial Content)

在传输大容量数据时,通过将数据分分割成多块,让浏览器逐步显示.需要在响应头设置相关信息:

'Content-Range': 'bytes chunkStart-chunkEnd/chunkSize'
'Accept-Ranges': 'bytes'
'Content-Length': chunkSize
'Content-Type': 'video/mp4'

浏览器在请求视频时会自动设置所需的ranges,所以后台需要获取请求头部的ranges信息,返回指定范围的数据

  • 5001-10000字节
Range: bytes=5001-10000
  • 从5001字节之后的所有数据
Range: bytes=5001-

后台实现

  app.get('/video', (req, res) => {const videoName = req.query.nameconsole.log('name', videoName)console.log(req.headers)const videoPath = `${VIDEO_DIR}${videoName}`const videoState = fs.statSync(videoPath) // video file's sizeconst videoSize = videoState.sizelet range = req.headers.rangerange = Array.isArray(range) ? range[0] : rangeif (range) {const parts = range.replace(/bytes=/, '').split('-')const start = parseInt(parts[0], 10)const end = parts[1] ? parseInt(parts[1], 10) : videoSize - 1const chunkSize = (end - start) + 1const file = fs.createReadStream(videoPath, {start, end})const head = { // https://stackoverflow.com/questions/41521272/html5-video-element-not-requesting-end-range // https://stackoverflow.com/questions/48156306/html-5-video-tag-range-header'Content-Range': `bytes ${start}-${end}/${videoSize}`,'Accept-Ranges': 'bytes','Content-Length': chunkSize,'Content-Type': 'video/mp4',}res.writeHead(206, head)file.pipe(res)} else {const head = {'Content-Length': videoSize,'Content-Type': 'video/mp4',}res.writeHead(200, head)fs.createReadStream(videoPath).pipe(res)}
})

前端的简单实现

<video id="videoPlayer" controls><source src="http://localhost:3000/video" type="video/mp4">
</video>

致此,完成简单的知乎视频下载播放的功能.

其他

html自动加载视频

<video id="videoPlayer" controls><source src="http://localhost:3000/video" type="video/mp4">
</video>
const myVideo = document.getElementsByTagName('video')[0]
myVideo.src = `http://${HOST}:${PORT}/video?name=${videoName}`
myVideo.load()
myVideo.play()

axios下载视频

后台实现

app.get('/download', async (req, res) => {
const url = req.query.url
const name = req.query.name
download(url, name).then(videoName => {let currentFile = `${VIDEO_DIR}${videoName}`console.log(currentFile)fs.exists(currentFile, function (exists) {if (exists) {res.download(currentFile)} else {res.set("Content-type", "text/html")res.send("file not exist!")res.end()}})
}).catch(err => {console.log(err)res.statusCode = 500res.end()
})
})

前段实现

// Download the files
const url = window.URL.createObjectURL(new Blob([response.data]))
const link = document.createElement('a')
link.href = url
link.setAttribute('download', videoName)
document.body.appendChild(link)
link.click()

下载知乎视频并在线播放相关推荐

  1. python实战笔记之(8):下载知乎视频

    这篇想写很久了,今天专门搞了搞,现在把用python下载知乎视频的整个流程码下来. (1)目标站点分析 比如这篇知乎文章https://www.zhihu.com/question/279247693 ...

  2. 服务器在线看视频无法播放,上传到服务器的视频不能在线播放怎么办?

    原标题:上传到服务器的视频不能在线播放怎么办? 问题:我们在本地测试视频播放时,常常遇到这种情况,本地测试视频是可以正常播放的,但项目上传服务器后,视频就无法播放了,原因通常有以下几种,原因及解决方案 ...

  3. 怎么下载知乎视频,怎么下载M3U8,利用FFMpeg下载M3U8并转成mp4格式

    昨天一个朋友问我怎么下载知乎视频,这有何难F12,找到视频链接打开就下载了啊.但是,可但是,但可是,我并没有成功. 查了很多资料,知乎使用的是M3U8视频.我还不太懂什么是M3U8,大概就是把视频切成 ...

  4. python需要花钱下载吗_用Python下载知乎视频,非常实用

    原标题:用Python下载知乎视频,非常实用 Python下载知乎视频. # -*- coding: utf-8 -*- """ 下载知乎视频: 依赖: pip inst ...

  5. android xml mpg格式,急求: android如何对mpg格式视频实现在线播放?

    急求: android怎么对mpg格式视频实现在线播放??? 对于3GP格式的视频都直接可以进行播放,但是对mpg格式谈话对话框提示无法播放此视频.是不是mpg格式的还需要我特别进行格式转化呢? 播放 ...

  6. 上传服务器上的视频不能在线播放的解决方案合集

    问题:我们程序员在本地测试视频播放时,常常遇到这种情况,本地测试视频是可以正常播放的,但项目上传服务器后,视频就无法播放了,原因通常有以下几种,原因及解决方案如下: 一.视频编码格式 以MP4为例,虽 ...

  7. 基于Python SimpleHTTPServer.py的修改脚本:HTTP文件服务器,修正中文目录列表,支持视频文件在线播放

    # -*- coding: gbkimport SimpleHTTPServer import BaseHTTPServer import time import SocketServer impor ...

  8. 趣闻-如何下载知乎视频

    打开带视频的知乎链接.比如: 右键查看网页源代码,可以看到一大堆眼花缭乱的代码. Ctrl f 查找 video-box,可以看到后边跟了个链接.class="video-box" ...

  9. 如何全自动下载知乎上的视频到本地

    比如这种 https://zhuanlan.zhihu.com/p/33805972?group_id=946815716536619008&utm_source=wechat_session ...

  10. android视频恢复播放器,AndroidVideoPlayer在线播放视频

    AndroidVideoPlayer在线播放视频 AndroidVideoPlayer在线播放视频,自定义SuperVideoPlayer里面封装了startPlayVideo()播放视频 loadA ...

最新文章

  1. 元学习(meta learning) 最新进展综述论文,28页pdf
  2. 修复思维导图mindmanager移动文件位置后打开崩溃
  3. 对付网络盗贼的三板斧
  4. php显示发件人地址吗,php – 发件人地址被拒绝
  5. 牛客题霸 [三个数的最大乘积]C++题解/答案
  6. Fitness - 05.23
  7. oracle把两个字段拼接在一起,请问Oracle中两个日期拼接在一起的语句应该怎么写?...
  8. tiktok+独立站怎么引流?
  9. 夸大 iPhone 防水功能?苹果遭起诉,曾已被罚 1200 万美元
  10. 软件核心研发迎来又一春!
  11. Python 和Java 哪个更适合做自动化测试?
  12. ffmpeg转码命令
  13. 揭开,字节跳动全链路压测的实践之路
  14. C语言计算圆周率小数后10位,计算圆周率Pi(π)值,精确到小数点后10000位 - 圆周率10000位 - C++ 爱好者...
  15. 西门子PLC程序调试方法
  16. 纯CSS实现数据上报和HTML验证
  17. 电子技术基础(三)__电感的感抗_无功功率和电容的容抗_无功功率
  18. 最新表情包小程序+前后端去授权版/最火表情包小程序源码
  19. tf.estimator.train_and_evaluate 详解
  20. 读《大话数据结构》溢彩加强版

热门文章

  1. word 无法启动转换器wps32修复工具
  2. win10绿联usb转串口_绿联usb转串口驱动
  3. 苹果cmsV10简约白色风格自适应模板
  4. matlab对多维数组转置,C++向matlab engine传递二维数组,互为转置
  5. 计算方法实验(二):龙贝格积分法
  6. 434个H5游戏源码
  7. CMMI认证难度大吗?
  8. 【集成电路 - -芯片】
  9. 海康大华网络录像机摄像机设备几种NTP校时方法
  10. AMOS分析技术:路径分析的非递归模型