4行代码播放当前目录下的所有mp3-乱序,技术路线摸索的过程

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

或者

https://ss64.com/nt/syntax-random.html#:~:text=Two%20commonly%20given%20ways%20to%20generate%20a%20random,_rand%3D%20%28%25RANDOM%25%2A%20500%20%2F32768%29%2B1%20Echo%20Random%20number%20%25_rand%25

看这里。

差不多,测试一下。用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行代码写了半小时,绝大部分时间都是在搜索、实验。这些弯路对于当前项目而言可以不是必须​的,但是对于整个职业生涯甚至对整个人生而言,那既是以后可用的经验,是对探索技术方案的训练和演习​,同时也是​沿途美丽的风景。

 

Leave a Reply

Your email address will not be published. Required fields are marked *