一、出现问题

人在美国,开的车没有中文显示,导致听歌时候不知道那个是什么名字,于是我想写一个electron+vue的一个程序,转化我的音乐文件为拼音.

中文转拼音字典

let dict={ "a": "\u554a\u963f\u9515", "ai": "\u57c3\u6328\u54ce\u5509\u54c0...", "an": "\u978d\u6c28\u5b89\u4ffa\u6309\u6697...", ... ... }

以这种形式把拼音对应的中文放在一起.然后得到这样的一个数据字典.

进行翻译

因为字典采用的是unicode编码,所以console.log("\u554a"),后台直接输入"啊" 换句话说就是"\u554a"=="啊" 是true. 根据这个,我们只需要遍历这个字典就可以了. 假如陈奕迅的《孤勇者》那么我们编译出来就是guyongzhe,可是这样的话就不太直观,所以要不驼峰命名法,要不空格隔开每个字.由于我不知道我车的中控能显示的效果,于是我2种方式我都写了.

//首先先为每一个字开头大写,把String的原型扩展一下,添加一个方法方便使用 String.prototype.firstUpperCase = function(){ return this.replace(/\b(\w)(\w*)/g, function($0, $1, $2) { return $1.toUpperCase() + $2.toLowerCase(); }); } /** * @param {string} zh : 输入的文字, * @param {boolean} isCapitalFirstLetter : 是否首字母大写,默认全部小写 * @return {string} 返回转义后的拼音 */ export function zh2pinyin(zh,isCapitalFirstLetter){ let py=""; for(let val in dict){ if(dict[val].indexOf(zh)!=-1){ py=isCapitalFirstLetter?val.firstUpperCase():val; break; } } return py==""?zh:py; };

zh2pinyin(zh,isCapitalFirstLetter) 只是单个文字转换,我们还需要将整个歌名转换.

/** * @param {string} words 一串需要转换的文字 * @param {boolean} isNoSpace 是否有空格, 默认每个拼音之间都有空格,如果没有空格则会用驼峰命名法 * @returns {string} 返回转移后的拼音 */ export function words2Pinyins(words,isNoSpace){ let space=isNoSpace?"":" "; let pinyins=""; let wordsArr=words.split("") wordsArr.forEach(word=>{//遍历每个字,进行转义拼凑. let sp=space //每个字后面空格 if(/^[0-9a-zA-Z\s+\.\`\']/.test(word)) sp="" //是否是英文数字,或者" . " ,是的话不需要空格. pinyins+=zh2pinyin(word,isNoSpace)+sp }) return pinyins }

万事俱备,可以用了.

繁体字转换简体字

等等 ~ ~ ~啥??还有问题? 是的,因为中文有简体繁体字,某些特殊渠道拿到的歌也许是繁体的.于是我还需要写一写方法转换

因为繁体字,简体字,基本是一一对应的,所以我们不需要用对象方式的字典,我们只需要一个个将有繁体字的排成一个字符串,分别写成简体繁体2个字符串.我这里就把这两个字符串再打包再一个数组里面.

let dictionarys = [ '锕皑蔼碍爱嗳....', '錒皚藹礙愛噯....' ]

为了以后可以复用这个方法,我把繁简呼唤的方法写出来

/** * @param {string} word 输入文字 * @param {boolean} isS2T 是否简体转换繁体 * @return {string} 返回翻译后的文字 */ function zhConvert(word,isS2T){ let wordsPool=isS2T?dictionarys[0]:dictionarys[1] // 原始字库 let convertPool=isS2T?dictionarys[1]:dictionarys[0] // 转义字库 let converted=word if(wordsPool.indexOf(word)!=-1){//判断word 是不是在原始字库里面,是的话进行转义 converted=convertPool.charAt(wordsPool.indexOf(word)) } return converted }

为了方便使用我单独暴露2个函数,分别繁体转简体,和简体转繁体

/** * @param {string} word 输入文字 * @return {string} 返回翻译后的文字 */ function simplified2Traditional(word){ return zhConvert(word,true) } /** * @param {string} word 输入文字 * @return {string} 返回翻译后的文字 */ function traditional2Simplified(word){ return zhConvert(word) } export {simplified2Traditional,traditional2Simplified}

最后别忘记把zh2pinyin函数修改,因为拼音字典都是简体,所以直接将繁体转简体

/** * @param {string} zh : 输入的文字, * @param {boolean} isCapitalFirstLetter : 是否首字母大写,默认全部小写 * @return {string} 返回转义后的拼音 */ export function zh2pinyin(zh,isCapitalFirstLetter){ let py=zh; let zh2=traditional2Simplified(zh, true)//将繁体字转换简体字 for(let val in dict){ //查找文字进行遍历,查找对应的拼音 if(dict[val].indexOf(zh2)!=-1){ py=isCapitalFirstLetter? val.firstUpperCase(): val; break } } return py; };

自此完成汉字转拼音的函数

二、修改文件

做完拼音转换,那么就开始转换我们的音乐文件的信息了.当然转换信息,我们需要复制文件,毕竟我们的文件是要放在车里的.

import { words2Pinyins } from "./pinyinConvert.js"; import fs from "fs" let songs=[] let path="d:\\desktop\\music" //待转换的文件夹 let newPath=paht+"_new" //转换后的文件,以复制形式修改文件,避免污染源文件. fs.mkdir(newPath,()=>{ fs.readdir(path,(err,files)=>{ if(err){ return console.log("目录不存在",err); } songs=files songs.forEach(element => { let music=words2Pinyins(element,true) fs.copyFileSync(path+"/"+element,newPath+"/"+music) console.log(music) }); }) })

轻轻松松解决文件名字修改,收工

三、出现错误

本以为写一个这么简单的东西就可以解决显示问题,结果还是太年轻了.只因为吃了不懂得音乐文件的信息的亏. 播放器显示音乐文件的信息,并不是文件名来显示.我这个只是简简单单修改文件名,对于那些音乐信息(tags信息)完全没有的文件,这个写法还可以凑合用.问题是,大部分音乐文件都不会什么都没.所以注定这个写法失败.

而这些文件信息,存在于音乐文件最后那堆字符串里面.以二进制形式.还有很多模式,什么id3,id4 之类的.

于是我爬网找一些有没相关的api,我在npm.io 上找到2个模块.于是开整.

其中一个是node-id3 另一个是jsmediatags

最后我选择的是node-id3

npm i node-id3 --save

最后是

import { words2Pinyins } from "./pinyinConvert.js"; import ID3 from "node-id3" import fs from "fs" let songs=[] let path=`d:\\desktop\\music` let newPath=path+"_new" //path=newPath fs.mkdir(newPath,()=>{ fs.readdir(path,(err,files)=>{ if(err){ return console.log("目录不存在",err); } //console.log(files) songs=files songs.forEach(element => { let music=words2Pinyins(element,true) fs.copyFileSync(path+"/"+element,newPath+"/"+music) console.log(music.replace(".mp3","").replace(".MP3","")) let tags={//修改的信息,我这里写死了,因为我不想多余信息影响界面.根据自己需要修改. title:music.replace(".mp3","").replace(".MP3",""), artist:"Eason Chan", album:"1" } console.log(ID3.write(tags,newPath+"\\"+music)) }); }) //console.log(ID3) })

搞掂,就看看能不能显示了.,所有东西都准备好,下一章就开始制作桌面应用,

修改图片

修改tags信息其中一个作为娱乐项目就是修改图片,我就把自己的歌全改了自己的头像. 当然还是用node-id3 修改tags信息

node-id3里面tags对象用imageraw的APIC保存图片信息.

tags={ ... image:{ ... "imageBuffer":"<Buffer 08 95...>", ... }, ... raw:{ ... APIC:{ ... "imageBuffer":"<Buffer 08 95...>", ... } } ... }

所以我们只需要将我们需要的图片用二进制形式读取后,写到这两个位置就可以了.

import ID3 from "node-id3" //读取我们需要的图片 fs.readFile(path+"\\myImage.jpg",(errImg,imgData)=>{ if(errImg) throw errImg; ... // 我把原来的tags信息全拿过来,只修改imageBuffer let {image,raw} = ID3.read(path) image.imageBuffer=imgData; raw.APIC.imageBuffer=imgData let tags={ title:music.replace(".mp3","").replace(".MP3",""), artist:"Eason Chan", image, raw } ... })

就这样吧图片内嵌到歌文件里面.

有没有直接放图片链接呢?那么就不用搞得每首歌都那么大啊.抱歉我查文档时没发现node-id3有对这个修改.所以后续我会再找找有没其他的api可用,又或者自己写一个用来修改...但,有模板,谁又想再造轮子呢?

版权声明:

1、该文章(资料)来源于互联网公开信息,我方只是对该内容做点评,所分享的下载地址为原作者公开地址。
2、网站不提供资料下载,如需下载请到原作者页面进行下载。