0. 为什么写这一篇
上一篇 一行代码播放当前目录下的所有mp3 https://zhuanlan.zhihu.com/p/666243724 有个缺陷,mp3未排序。播放如果总是同一次序,那么听到的就总是那么几首曲子,后面200多首没机会听到,让我想起当年背单词多少次止于abandon。
不可忍,所以实现了一个乱序播放的版本。
读我博客或者技术讨论的时候,有的同学提到过,你能做出来是因为你已经了解那些知识,而且记住了。不总是这样,我经常想不起来具体的技术细节,需要搜索。这篇以乱序播放为例,回顾我实现的过程——在知识点记不清的时候。
以下是实现的过程,总计半小时左右。
1. bat 批处理
上一篇是用bat实现的,核心技术包括 遍历目录、调用ffmpeg、播放完每首歌曲后退出到bat再进入循环。批处理是windows原生的,如果不需要引入任何运行环境,那最好不过。所以这一次也想继续用bat。
我需要哪些技术呢?生成随机数,指定随机数范围,建立数组,遍历数组。也许需要平行数组,一个用来存随机数,一个用来存文件名。
都依稀记得,然而印象不清晰,不足以不搜索就写代码。以下依次搜索如何实现。
(1)随机数
乱序,或者随机播放,核心因素是随机。我需要生成随机数,不必太真实,所以伪随机如何才能更真,就超出了考虑范围。
我不知道如何生成随机数。
搜索bing,国际版,关键词 bat, random。关键词指定得如果不是编差太多,一般不会超过第一页。这次幸运,没有超过第5个的,一般都在第3条以内。
看第一条
https://www.delftstack.com/howto/batch/batch-random-number-generator/
里面有这样一段代码。
就是它了,测试一下,很对。
(2)需要指定随机数的生成范围,从第1首到最后一首。
Bing搜索关键词, bat random range。
第1篇,似乎被墙,出现有点慢。
https://ss64.com/nt/syntax-random.html
或者
看这里。
差不多,测试一下。用Total Commander | ctrl-f | mp3 搜索,看计数263首。需要随机数落在[1,263]这个区间范围内。
差不多。
(3)数组
搜索。
咋只有赋值没有声明呢?看到下面这里,所有的记忆突然复苏了。
Bat是用字符拼出来的数组,实现起来非常丑陋。
放弃bat这条思路。同学们经常觉得别人实现多么顺利,以为自己很菜。并不是,如果你看到菜成像我这样的,把菜的过程都揭示出来 ,就会明白你并不孤独,可能比我还要厉害或者幸运一些呢。人人惨淡,只是在朋友圈里晒得是最高兴的部分就是了。
2. bash
换用bash吧。我机器里刚好已经装了git,附赠了bash。
我刚好学过一点bash,用过一点。虽然忘得快干净了,但是具体细节可以搜索。需要哪些技术呢?
跟bat的一样,并且我确实做了计划。搜索和实验的过程记录在计划的大纲下面。
(1)随机数
搜索 bash random
找到 https://linuxconfig.org/generating-random-numbers-in-bash-with-examples
测试 echo $RANDOM
(2)随机数范围
我在日志中记录了 搜索,参考的链接,实验,如下。
(3)改变路线,洗牌
在看下面这篇时,我突然想到,可以不必随机数。
即这一篇,刚刚搜索到的第1条。
https://www.baeldung.com/linux/bash-draw-random-ints
这篇对随机还给出了其他方案,例如 shuf,可以乱序集合中的元素。
那么我这样不就很好?
ls | shuf
每次执行输出的文件名次序不同。
3. 改变路线,洗牌
可以不需要随机数——乱序遍历。相当于用 foreach 语法而不用 for i=0 这样的循环。
步骤如下:
列出当前目录下所有文件;
洗牌得到文本;
执行文本。
因为不熟悉这些技术,忘得几乎一干二净,所以以上步骤也就是要搜索的知识。
(1)列出当前目录下所有文件,乱序输出文件名。
列目录,这个我会,ls。参数我忘了,那就啥也不给。
看下面这两张截图,指令完全相同“ls | shuf”,输出的开始部分非常不同。乱序效果符合期待(存在可能,每次执行的随机序列都是相同的,如果出现这种情况,到时候再说。);文件格式也符合ffplay的要求,没有后缀、日期时间之类的。
(2)执行文本
我们所希望的并不是输出文本,而是执行它们。
怎么执行一段文本?忘了。忘了不要紧,搜索。
测试,好使。
(3)拼接文本
根据上篇文章已知,我需要这样的效果
ffplay 歌曲的文件名.mp3 -autoexit
要求有参数。
在整行中,两边是固定内容,中间夹着一段变量。
那么需要字符串拼接。
要么是“+”号,要么是空格。
我先测试了“+”,失败了。我没有气馁,因为原计划的列表尚未穷举。又测试了空格,好使。我也并不非常高兴,反正就是这么几个方案,挨个测下去总有一个会行。如果都不行,才需要停下来再想想。
: eval 'ffplay' '歌曲的文件名.mp3' '-autoexit'
(4)四行代码
又搜索了一下bash里的循环怎么写,有了以下代码。
for i in `ls | shuf`
do
eval 'ffplay' $i '-autoexit'
done
命名为 play.sh,运行。
可用,每次运行都随机。就像久未谋面的老友,猛一见到,恍如隔世。
这个方案的现存缺陷是 每次播放新的一首歌曲,ffplay就会跳出来成为顶层窗口,需要手动切一下到后面。上篇提到,可以用 -nodisp 参数避免打开GUI窗口,但是这样我就失去了用q切到下一首歌的渠道。没找到办法,忍吧。
4行代码写了半小时,绝大部分时间都是在搜索、实验。这些弯路对于当前项目而言可以不是必须的,但是对于整个职业生涯甚至对整个人生而言,那既是以后可用的经验,是对探索技术方案的训练和演习,同时也是沿途美丽的风景。