背景
B站上有不少的学习视频,可是在手机上缓存比较占用空间,所以在Win10上通过store安装了b站的客户端。通过设置可以进行缓存操作。设置位置为下载&缓存>自定义视频下载路经。
有些在线的视频由于某些原因会失效,缓存在电脑上又没有手机和平板电脑山看着方便。 所以想把视频转到百度云上去。
看了下缓存目录的结构。每个系列视频下由一个dvi文件和许多目录组成。而每个目录下则根据下载时候的选项如FLV还是MP4格式会有按照数字和格式的多个文件组成。
1mp4
2.
3├── 1
4│ ├── 711036321_1.xml
5│ ├── 711036321.info
6│ ├── audio1.mp4
7│ └── video.mp4
8├── 10
9│ ├── 711036321_10.xml
10│ ├── 711036321.info
11│ ├── audio1.mp4
12│ └── video.mp4
13├── 711036321.dvi
14└── cover.jpg
15
16flv
17.
18├── 1
19│ ├── 98073910_1_0.flv
20│ ├── 98073910_1.xml
21│ └── 98073910.info
22...
23├── 9
24│ ├── 98073910_9_0.flv
25│ ├── 98073910_9.xml
26│ └── 98073910.info
27├── 98073910.dvi
28└── cover.jpg
问题描述
主要有两个问题。
- 由于文件名都是数字格式,看起来很不直观。
- mp4格式下载时候音视频会分开。
所以希望能够按照在客户端里的显示的标题信息来重命名视频文件,并且合并音视频文件。
问题分析
在根目录下有一个 .dvi 文件,这是一个Json格式的文本文件。这个里面可以看到这个视频系列的一些信息,比如up主的id,系列的名称"Title"以及上传时间封面图等。
1{
2 "Aid": "711036321",
3 "Bid": "********",
4 "SeasonId": null,
5 "EpisodeId": null,
6 "Title": "Excel powerpivot进阶",
7 "Uploader": "********_bili",
8 "Mid": "353517311",
9 "Description": "超级透视表",
10 "CoverURL": "*****.jpg",
11 "Tag": null,
12 "DownloadTimeRelative": 181424766,
13 "CreateDate": "2020-06-13 07:58",
14 "IsBangumi": false,
15 "Is360": false,
16 "TotalTime": "00:00:00",
17 "Parts": null
18}
而在每一个视频的目录下有一个aid为文件名的.info文件,同样是json格式。这里面有该分段视频的名称"PartName"。至此已经得到了所需要的信息。
1❯ cat *****9566.info |jq .
2{
3 "Type": 0,
4 "Aid": "****59566",
5 "Bid": "BV******",
6 "Cid": "********",
7 "SeasonId": null,
8 "EpisodeId": null,
9 "Title": "Excel powerquery 基础",
10 "Uploader": "xxxxx",
11 "Description": "数据整理清洗输出",
12 "CoverURL": "*****.jpg",
13 "Tag": null,
14 "From": "vupload",
15 "PartNo": "30",
16 "PartName": "30 多行属性合并(Text.Combine)",
17 "Format": 2,
18 "TotalParts": 2,
19 "DownloadTimeRelative": 181425281,
20 "CreateDate": "2020-06-12 09:29",
21 "TotalTime": "00:15:46.5360000",
22 "PartTime": [
23 946536,
24 0
25 ],
26 "TotalSizeByte": 44295342,
27 "IsSinglePart": false,
28 "IsDash": true,
29 "IsMerged": false,
30 "VideoInfo": {
31 "MediaType": 0,
32 "CodecId": 7,
33 "CodecName": "avc1.64001F",
34 "VideoWidth": 960,
35 "VideoHeight": 540,
36 "Bandwidth": 245484,
37 "FrameRate": 25
38 },
39 "AudioInfo": [
40 {
41 "MediaType": 1,
42 "CodecId": 0,
43 "CodecName": "mp4a.40.2",
44 "VideoWidth": 0,
45 "VideoHeight": 0,
46 "Bandwidth": 128928,
47 "FrameRate": 0
48 }
49 ]
50}
51
解决方案
1#!/usr/bin/env bash
2# Combining mp4 files of bb download files
3# Renaming media files with title name
4
5aid=`find . -name *.dvi | cut -f2 -d/ | cut -f1 -d.`
6IFS_OLD=$IFS
7
8title=`cat *.dvi | jq '.Title'|sed -e 's/"//g'`
9IFS=$(echo -en "\n\r")
10if [ ! -d ${title} ]; then
11 mkdir $title
12fi
13
14for x in `find . -type d |grep -v ^.$| grep -v $title`
15 do
16 pid=`basename $x`
17 cd $pid
18 echo "Processing $pid"
19 echo "-----------------"
20
21 if [ -f $aid.info ]; then
22 name=`cat *.info | jq '.PartName'|sed -e 's/"//g'`
23 if [ -f video.mp4 ]; then
24 echo "Combining audio and video files..."
25 ffmpeg -i audio1.mp4 -i video.mp4 -hide_banner -c copy \
26 ../$title/$name.mp4 -y -stats 2>/dev/null && echo Done
27 else
28 echo "Already combined, copying .."
29 ls *.mp4 &>/dev/null && cp ${aid}*.mp4 ../$title/$name.mp4 \
30 && echo done
31 ls *.flv &>/dev/null && cp ${aid}*.flv ../$title/$name.flv \
32 && echo done
33 fi
34 else
35 echo "No video files in $pid"
36 fi
37 cd ..
38 echo " "
39done
40
41IFS=$IFS_OLD
这个过程比较简单,在每一个系列的根目录下执行,就会生成一个系列名称的目录,目录下就是各个章节名命名的文件。
1❯ ../convert.sh
2Processing 1
3-----------------
4Combining audio and video files...
5Done
6
7Processing 10
8-----------------
9Combining audio and video files...
10Done
11
12❯ tree
13.
14├── 课时03.创建一个日历表.mp4
15├── 课时04.年累计(YTD)&季度累计(QTD)&月累计(MTD).mp4
16├── 课时05.计算同比(YOY)和环比(MOM).mp4
17...
18└── 课时09.使用链接回表进行RFM分析.mp4
19