网站底部链接代码,泉州仿站定制模板建站,广东中山网站建设 光龙,智能家居最近呢#xff0c;买了一个 iPad#xff0c;虽然家里笔记本台式都有#xff0c;显示器都是 2个#xff0c;比较方便看代码#xff08;边打游戏边追剧#xff09;。
但是在床上拿笔记本始终还是不方便#xff0c;手机在家看还是小了点#xff0c;自从有 iPad 之后…最近呢买了一个 iPad虽然家里笔记本台式都有显示器都是 2个比较方便看代码边打游戏边追剧。
但是在床上拿笔记本始终还是不方便手机在家看还是小了点自从有 iPad 之后拿个大屏在家里用着确实舒服不少。
能追剧能玩玩其他应用那还得听听音乐不是但是懂的都懂苹果里导入文件是个麻烦事更别说音乐播放。
所以这件事就得研究研究因为在电脑上已经把音乐都按照文件夹整理好了。
在 Android 中很简单adb 一推到 Music 目录中更新一下就行。 但是 iOS 搜了一圈发现还真不好弄基本都是要通过 Apple 这个音乐导入到资料库接着再通过 iTunes新版已经合并在 Finder 中 进行同步。
我试了下音乐这个应用确实是可以通过新建歌单后把需要添加的音乐文件夹直接拖入到歌单中这样一次就可以添加多首这个虽然要操作一下但是也还可以接受。
正当我发现这个方案可行的时候我看了一眼歌单发现只有部分歌就有点纳闷为啥部分歌曲没有导入。 在网上一搜发现原来不支持无损就是 FLAC 格式的文件。
这不是尴尬了么所以看来还需要一个操作把 FLAC 文件转为 mp3 格式再导入才可以。
如果选第三方的工具比如格式工厂或者狸窝文件夹太多的情况都要自己动手就太折腾了比如我这里有几十个文件夹。别问为啥这么多强迫症就是歌手区分各种风格也要区分
用过 shell 的朋友都知道这种批量的工作最好就交给脚本来做遍历文件夹批量转化所有文件就行。
批量转化音乐
当然这里还有一些其他的逻辑比如歌曲中已经是 mp3 的格式了那应该就直接复制除了 mp3 还有 wav 格式同理针对 lrc 歌词文件也应该是直接复制。
所以和 ChatGPT “对线”几轮后终于得到了一个满意的脚本就不卖关子了。对线真的考验心态和血压最好自己能懂部分可以自己动手改一下 shell
#!/bin/bash# 检查是否安装了 ffmpeg
if ! command -v ffmpeg /dev/null
thenecho Error: ffmpeg 未安装。请先安装 ffmpeg。exit 1
fi# 检查参数是否足够
if [ $# -ne 2 ]; thenecho Usage: $0 import_directory export_directoryexit 1
fi# 输入和输出目录
import_dir$1
export_dir$2
error_log$export_dir/error_log.txt# 检查导入目录是否存在
if [ ! -d $import_dir ]; thenecho Error: 导入目录 $import_dir 不存在。exit 1
fi# 创建导出目录如果不存在
mkdir -p $export_dir# 清空错误日志文件
: $error_log# 查找所有文件并计算文件总数
total_files$(find $import_dir -type f | wc -l)
if [ $total_files -eq 0 ]; thenecho Error: 未找到文件。exit 1
fiecho 共找到 $total_files 个文件开始处理...# 初始化计数器
counter1# 遍历所有歌手目录
for artist_dir in $import_dir/*; doif [ -d $artist_dir ]; then# 遍历每个歌手目录下的所有文件for song in $artist_dir/*; doif [ -f $song ]; then# 确定输出文件夹结构rel_path${song#$import_dir/}output_dir$export_dir/$(dirname $rel_path)mkdir -p $output_dir# 获取文件扩展名ext${song##*.}# 处理不同文件类型if [ $ext flac ]; then# 转换 FLAC 文件为 MP3指定比特率 320k并显式指定编码器output_file$output_dir/$(basename ${song%.flac}.mp3)echo 正在转换文件 ($counter/$total_files): $song - $output_file# 使用 libmp3lame 编码器忽略非音频流并增加 analyzeduration 和 probesizeffmpeg -analyzeduration 100M -probesize 50M -i $song -vn -c:a libmp3lame -b:a 320k $output_file /dev/null 2 ffmpeg_errors.txtif [ $? -ne 0 ]; thenecho Error: 转换 $song 失败。 | tee -a $error_logelseecho 转换成功: $output_filefielif [ $ext lrc ] || [ $ext mp3 ] || [ $ext wav ]; then# 直接复制 LRC 和 MP3 文件echo 正在复制文件 ($counter/$total_files): $song - $output_dir/cp $song $output_dir/if [ $? -ne 0 ]; thenecho Error: 复制 $song 失败。 | tee -a $error_logelseecho 复制成功: $songfielseecho 跳过不支持的文件 ($counter/$total_files): $songfi# 更新计数器counter$((counter 1))fidonefi
doneecho 所有文件已处理完成。总结几个点
这里是通过 ffmpeg 进行转换毕竟这个开源工具很强大视频都能随便处理音频处理不是手到擒来么。加入了处理进度会在控制台输出这样我们比较好知道处理到哪了大概还有多久的时间。第三是加入了错误日志导出这样知道哪些歌曲出错了没有处理。
因为脚本上也有对应的注释如果知道一点编程的朋友应该能知道怎么修改一下。但是呢考虑到可能会有非程序员的朋友看到该文章还是简单讲一下这里的操作的流程。 打开终端应用。 在里面输入下面的语句这个是通过 brew 命令安装 ffmpeg 库。
brew install ffmpeg当命令行自己运行一会光标重新开始闪烁时一般就是安装完毕。可以通过查看下 ffmpeg 版本看下是否安装好了。
ffmpeg --version这样就完成了第一步 ffmpeg 安装。接着我们通过命令要新建一个普通文件命名为 cvt.sh 意思就是 converte 缩写当然可以换个任意你喜欢的名字。
touch cvt.sh一般来说命令行首次打开会在自己的 home 目录下那么新建也是在这里。 如果会用命令修改的话可以直接通过 vi 打开复制不会的朋友找到这个文件然后用文本编辑应用打开。把刚刚那一长串代码复制进去就像这样记得保存一下。(Command s) 第二部脚本文件可以说准备好了但这里还差一点就是新建的脚本文件需要加上可执行的权限。
在命令行中输入这样我们一会才能执行这个转化的脚本。
chmod 711 cvt.sh万事具备讲一讲这个用法。输出的文件夹可以不用存在会自动创建
#这里需要把对应的文件夹名字换一下。
bash cvt.sh 输入的文件夹 输出的文件夹这里还要说明一下脚本扫描的路径层级是这样 输入的文件夹 - 二级目录一般是歌手或者歌曲风格 - 该目录下所有歌曲 如果二级目录这个位置是歌曲是不会处理的因为这么设计是为了方便后续导入 Apple 歌单. 我这里示范一下假如我的音乐 testMusic 和脚本在一个地方都在 home 目录下。
bash cvt.sh testMusic outputMusic这样就开始了可以看到有复制的有转换的也有对应进度。
需要注意的是因为这里把错误信息导出到文件了所以当第一次跑脚本中途取消了重新跑会发现命令行卡着不动实际上可以在当前目录中看到有错误日志这里提示问是否覆盖。 所以建议如果用这个脚本就一次性跑完或者需要重新跑的时候把目标文件夹清除一下。 当然更优秀的朋友应该知道根据自己需求改下脚本比如文件是直接强行覆盖不用询问么或者还是需要手动对比。当然每个人的想法不一样这里就是抛砖引玉。
这样的话音乐的转换就完成了。
如果只有几个歌单需要添加的朋友那么手动拖一下到 音乐 中就可以解决问题了。 批量导入歌单
接着就是到歌曲导入为 Apple 的歌单了。
从我前面的强迫症发言来看就知道我需要导入的歌单不少那这么多都需要操作一遍岂不是很麻烦所得想个招比如有没有办法用脚本来做所以懒惰才是人类的第一生产力。
问了下 gpt 好消息-有方案坏消息-是其他脚本。
Gpt 提到可以用 Mac 自带的脚本编辑器来做虽然我不会它这个脚本的语法但是我有 gpt 呀它会≈我会。
把导入的诉求告诉了它又是一顿 battle 。
算是最后拿出了一个脚本你还别说shell 都算语法奇怪的了苹果这个更奇怪不过 …… 反正能跑就是好代码不是。
照例加入进度打印错误输出。
on run argv-- 确保传入的参数数量正确if (count of argv) is not 1 thenerror 请提供一个参数音乐文件夹的根路径。end if-- 获取传入路径set inputPath to item 1 of argv-- 检查是否为相对路径若是则转换为绝对路径if inputPath does not start with / thenset currentDirectory to (POSIX path of (do shell script pwd))set rootFolderPathString to currentDirectory / inputPathelseset rootFolderPathString to inputPathend if-- 转换路径为 POSIX file 类型set rootFolderPath to POSIX file rootFolderPathString-- 设置日志文件路径set logFilePath to POSIX file (rootFolderPathString /import_log.txt)-- 强制启动音乐应用tell application Musiclaunch -- 确保 Music 应用已启动end tell-- 获取根文件夹下的所有文件夹tell application Finderset musicFolders to every folder of folder rootFolderPathend tell-- 清空日志文件tryset logFile to open for access logFilePath with write permissionset eof of logFile to 0 -- 清空文件close access logFileon error-- 如果日志文件不存在则创建它set logFile to open for access logFilePath with write permissionclose access logFileend try-- 总文件夹数量set totalFolders to count of musicFolders-- 遍历每个文件夹repeat with musicFolder in musicFoldersset playlistName to name of musicFolder -- 使用文件夹名作为播放列表名称set musicFolderPath to (musicFolder as alias)tell application Music-- 检查是否已经存在同名播放列表set playlistExists to falserepeat with aPlaylist in (get user playlists)if (name of aPlaylist) is equal to playlistName thenset playlistExists to trueset existingPlaylist to aPlaylistexit repeatend ifend repeat-- 如果不存在同名播放列表则创建新的播放列表if playlistExists thenset targetPlaylist to existingPlaylistelseset targetPlaylist to make new user playlist with properties {name:playlistName}log Created new playlist: playlistNameend if-- 获取该文件夹中的所有音乐文件tell application Finderset musicFiles to every file of musicFolderend tell-- 当前文件夹的已处理文件计数set processedFilesInFolder to 0 -- 初始化当前文件夹处理计数-- 将每个文件导入到音乐应用并添加到播放列表repeat with aFile in musicFilesset fileName to name of aFileset fileExtension to (name extension of aFile)log Checking fileName fileName ;fileExtension: fileExtension-- 只处理 .mp3 和 .wav 文件if fileExtension is mp3 or fileExtension is wav thentry-- 检查文件是否已经在播放列表中set songAlreadyInPlaylist to falselog File name: (name of aFile) -- 查看文件名repeat with aTrack in (get tracks of targetPlaylist)if (name of aTrack) is equal to fileName thenset songAlreadyInPlaylist to truelog Found existing song in playlist: fileNameexit repeatend ifend repeat-- 如果歌曲尚未在播放列表中才导入if not songAlreadyInPlaylist thenlog Importing song to playlist: fileName-- 确保 aFile 以 alias 形式导入set importedTrack to add (aFile as alias) to targetPlaylistlog Successfully added: fileName--delay 1 -- 添加 1 秒的延迟elselog Skipping already existing song: fileName--delay 1 -- 添加 1 秒的延迟end ifon error errorMsg-- 处理可能的错误记录详细信息set logMessage to Error importing file: fileName return errorMsgmy appendToLog(logMessage, logFilePath)end tryelse-- 记录不支持的文件到日志文件log Skipping unsupported file: fileNameend if-- 增加当前文件夹的已处理文件数量set processedFilesInFolder to processedFilesInFolder 1-- 打印当前进度my displayProgress(processedFilesInFolder, (count of musicFiles), playlistName)end repeatend tellend repeat-- 打印总的处理完成信息display dialog 所有歌曲已处理完成 buttons {OK} default button 1
end run-- 函数将消息附加到日志文件
on appendToLog(logMessage, logFilePath)set logFile to open for access logFilePath with write permissionwrite logMessage to logFile starting at eofclose access logFile
end appendToLog-- 函数显示处理进度
on displayProgress(folderProcessed, totalInFolder, playlistName)set progressPercent to (folderProcessed / totalInFolder) * 100set formattedProgress to round progressPercent * 10 / 10.0 -- 保留一位小数-- 在终端输出进度log Processing playlistName : (folderProcessed as string) / (totalInFolder as string) ( (formattedProgress as string) %)
end displayProgress关于这个脚本的用法简单讲一下估计大部分朋友都没有接触过毕竟不通用。 打开这个编辑器把刚才的脚本拷贝上然后保存为 脚本格式。 我这里文件名用的是 importMusic.scpt 说一下用法。
osascript 脚本名称 导入的文件夹和刚才一样我的命令行在 home 目录下新建的 importMusic.scpt 也挪到这个目录处理后的音乐还在刚才的位置。 那我就可以这么用。
osascript importMusic.scpt outputMusic接下来就是见证奇迹的时刻。 轻轻松松导入真是省大心。
当然最后可以把这一段执行代码再组合在前面的 shell 文档中不过分开一下也好各个朋友有各自的需求需求什么用什么。
脚本真是提升效率的利器。 后续计划录个视频把操作和代码上传一下如果有看视频来的朋友用起来就比较方便了。
如果对你有帮助请点赞收藏支持一下感谢 ~