add build script
parent
da7cef9cda
commit
f00514a562
|
@ -10,10 +10,10 @@ const __filename = fileURLToPath(import.meta.url)
|
|||
const __dirname = path.dirname(__filename)
|
||||
|
||||
|
||||
|
||||
// 脚本执行之前的操作
|
||||
var iosUrl = "https://apps.apple.com/app/legend-of-mushroom/id6475333787"
|
||||
var androidUrl = "https://play.google.com/store/apps/details?id=com.mxdzzus.google"
|
||||
var iosUrl = "https://apps.apple.com/us/app/top-heroes/id6450953550"
|
||||
var androidUrl = "https://play.google.com/store/apps/details?id=com.greenmushroom.boomblitz.gp&hl=en_US"
|
||||
|
||||
|
||||
removeDist()
|
||||
createDist()
|
||||
|
@ -67,9 +67,17 @@ async function startScript() {
|
|||
|
||||
const options = {
|
||||
// zip包
|
||||
zipChannel: ['facebook', 'google', 'tiktok', 'vungle', 'liftoff'],
|
||||
zipChannel: ['facebook', 'google', 'tiktok',
|
||||
'vungle', 'liftoff'
|
||||
],
|
||||
// html包
|
||||
htmlChannel: ['applovin', 'unity', 'appier', 'ironsource', 'mintegral', 'moloco'],
|
||||
htmlChannel: ['applovin',
|
||||
|
||||
'unity',
|
||||
'appier', 'ironsource',
|
||||
|
||||
'mintegral', 'moloco'
|
||||
],
|
||||
outputPrefix: ''
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,205 @@
|
|||
const sharp = require('sharp');
|
||||
const fs = require('fs').promises;
|
||||
const path = require('path');
|
||||
const ffmpeg = require('fluent-ffmpeg');
|
||||
|
||||
// 支持的图片格式
|
||||
const IMAGE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.webp'];
|
||||
const AUDIO_EXTENSIONS = ['.mp3'];
|
||||
|
||||
// 压缩配置
|
||||
const COMPRESSION_OPTIONS = {
|
||||
jpeg: {
|
||||
quality: 60, // 降低质量以获得更高压缩率
|
||||
mozjpeg: true, // 使用 mozjpeg 压缩
|
||||
chromaSubsampling: '4:2:0' // 更激进的色度采样
|
||||
},
|
||||
png: {
|
||||
quality: 60, // 降低质量
|
||||
compressionLevel: 9, // 最高压缩级别
|
||||
palette: true, // 使用调色板模式
|
||||
effort: 10, // 最大压缩效果
|
||||
colors: 128 // 减少调色板颜色数量以增加压缩率
|
||||
},
|
||||
webp: {
|
||||
quality: 60, // 降低质量
|
||||
effort: 6, // 最高压缩效果
|
||||
lossless: false, // 有损压缩
|
||||
nearLossless: false // 关闭近无损压缩
|
||||
}
|
||||
};
|
||||
|
||||
// 格式化文件大小
|
||||
function formatFileSize(bytes) {
|
||||
if (bytes < 1024) return bytes + ' B';
|
||||
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(2) + ' KB';
|
||||
return (bytes / (1024 * 1024)).toFixed(2) + ' MB';
|
||||
}
|
||||
|
||||
async function processDirectory(inputDir) {
|
||||
try {
|
||||
const items = await fs.readdir(inputDir);
|
||||
let totalOriginalSize = 0;
|
||||
let totalCompressedSize = 0;
|
||||
|
||||
for (const item of items) {
|
||||
const filePath = path.join(inputDir, item);
|
||||
const stats = await fs.stat(filePath);
|
||||
|
||||
if (stats.isDirectory()) {
|
||||
await processDirectory(filePath);
|
||||
} else if (stats.isFile()) {
|
||||
const ext = path.extname(item).toLowerCase();
|
||||
const originalSize = stats.size;
|
||||
|
||||
if (IMAGE_EXTENSIONS.includes(ext)) {
|
||||
await compressImage(filePath);
|
||||
} else if (AUDIO_EXTENSIONS.includes(ext)) {
|
||||
await compressAudio(filePath);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
const compressedStats = await fs.stat(filePath);
|
||||
const compressedSize = compressedStats.size;
|
||||
|
||||
totalOriginalSize += originalSize;
|
||||
totalCompressedSize += compressedSize;
|
||||
|
||||
const savedSize = originalSize - compressedSize;
|
||||
const savingPercentage = ((savedSize / originalSize) * 100).toFixed(2);
|
||||
|
||||
console.log(`已压缩: ${filePath}`);
|
||||
console.log(` 原始大小: ${formatFileSize(originalSize)}`);
|
||||
console.log(` 压缩后大小: ${formatFileSize(compressedSize)}`);
|
||||
console.log(` 节省: ${formatFileSize(savedSize)} (${savingPercentage}%)`);
|
||||
console.log('----------------------------------------');
|
||||
}
|
||||
}
|
||||
|
||||
if (totalOriginalSize > 0) {
|
||||
const totalSaved = totalOriginalSize - totalCompressedSize;
|
||||
const totalSavingPercentage = ((totalSaved / totalOriginalSize) * 100).toFixed(2);
|
||||
console.log(`\n当前目录 ${inputDir} 总计:`);
|
||||
console.log(` 原始总大小: ${formatFileSize(totalOriginalSize)}`);
|
||||
console.log(` 压缩后总大小: ${formatFileSize(totalCompressedSize)}`);
|
||||
console.log(` 总共节省: ${formatFileSize(totalSaved)} (${totalSavingPercentage}%)\n`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('处理出错:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function compressImage(filePath) {
|
||||
const ext = path.extname(filePath).toLowerCase();
|
||||
const tempPath = filePath + '.temp';
|
||||
const image = sharp(filePath);
|
||||
|
||||
try {
|
||||
// 获取图片信息
|
||||
const metadata = await image.metadata();
|
||||
|
||||
// 根据图片大小和类型选择压缩策略
|
||||
switch (ext) {
|
||||
case '.jpg':
|
||||
case '.jpeg':
|
||||
await image
|
||||
.jpeg(COMPRESSION_OPTIONS.jpeg)
|
||||
.toFile(tempPath);
|
||||
break;
|
||||
case '.png':
|
||||
// 如果PNG是透明的,保持PNG格式
|
||||
if (metadata.hasAlpha) {
|
||||
await image
|
||||
.png(COMPRESSION_OPTIONS.png)
|
||||
.toFile(tempPath);
|
||||
} else {
|
||||
// 如果PNG不是透明的,转换为JPEG可能会得到更好的压缩效果
|
||||
await image
|
||||
.jpeg(COMPRESSION_OPTIONS.jpeg)
|
||||
.toFile(tempPath);
|
||||
}
|
||||
break;
|
||||
case '.webp':
|
||||
await image
|
||||
.webp(COMPRESSION_OPTIONS.webp)
|
||||
.toFile(tempPath);
|
||||
break;
|
||||
}
|
||||
|
||||
// 检查压缩后的文件大小
|
||||
const originalStats = await fs.stat(filePath);
|
||||
const compressedStats = await fs.stat(tempPath);
|
||||
|
||||
// 只有当压缩后的文件更小时才替换
|
||||
if (compressedStats.size < originalStats.size) {
|
||||
await fs.unlink(filePath);
|
||||
await fs.rename(tempPath, filePath);
|
||||
console.log(` 压缩成功: ${formatFileSize(originalStats.size)} -> ${formatFileSize(compressedStats.size)}`);
|
||||
} else {
|
||||
// 如果压缩后反而更大,则删除临时文件保留原文件
|
||||
await fs.unlink(tempPath);
|
||||
console.log(` 跳过压缩: 原始大小 ${formatFileSize(originalStats.size)}, 压缩后 ${formatFileSize(compressedStats.size)}`);
|
||||
console.log(` 原因: 压缩后文件更大,已保留原文件`);
|
||||
}
|
||||
} catch (error) {
|
||||
try {
|
||||
await fs.unlink(tempPath);
|
||||
} catch (e) {
|
||||
// 忽略临时文件删除失败的错误
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function compressAudio(filePath) {
|
||||
const tempPath = filePath + '.temp';
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
ffmpeg(filePath)
|
||||
.toFormat('mp3')
|
||||
.audioBitrate(64) // 降低到64kbps以获得最大压缩
|
||||
.audioChannels(1) // 转换为单声道
|
||||
.audioFrequency(22050) // 降低采样率
|
||||
.audioCodec('libmp3lame') // 使用LAME编码器
|
||||
.addOptions([
|
||||
'-q:a 9', // 最高压缩质量
|
||||
'-compression_level 9' // 最高压缩级别
|
||||
])
|
||||
.on('end', async () => {
|
||||
try {
|
||||
// 检查压缩后的文件大小
|
||||
const originalStats = await fs.stat(filePath);
|
||||
const compressedStats = await fs.stat(tempPath);
|
||||
|
||||
// 只有当压缩后的文件更小时才替换
|
||||
if (compressedStats.size < originalStats.size) {
|
||||
await fs.unlink(filePath);
|
||||
await fs.rename(tempPath, filePath);
|
||||
console.log(` 压缩成功: ${formatFileSize(originalStats.size)} -> ${formatFileSize(compressedStats.size)}`);
|
||||
} else {
|
||||
await fs.unlink(tempPath);
|
||||
console.log(` 跳过压缩: 原始大小 ${formatFileSize(originalStats.size)}, 压缩后 ${formatFileSize(compressedStats.size)}`);
|
||||
console.log(` 原因: 压缩后文件更大,已保留原文件`);
|
||||
}
|
||||
resolve();
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
})
|
||||
.on('error', (err) => {
|
||||
reject(err);
|
||||
})
|
||||
.save(tempPath);
|
||||
});
|
||||
}
|
||||
|
||||
// 设置输入目录
|
||||
const INPUT_DIR = './assets';
|
||||
|
||||
// 运行脚本
|
||||
(async () => {
|
||||
console.log('开始处理图片压缩...');
|
||||
await processDirectory(INPUT_DIR);
|
||||
console.log('图片压缩完成!');
|
||||
})();
|
|
@ -1,6 +1,6 @@
|
|||
// 填入对应的商店地址
|
||||
var iosUrl = "https://apps.apple.com/app/legend-of-mushroom/id6475333787"
|
||||
var androidUrl = "https://play.google.com/store/apps/details?id=com.mxdzzus.google"
|
||||
var iosUrl = "https://apps.apple.com/us/app/top-heroes/id6450953550"
|
||||
var androidUrl = "https://play.google.com/store/apps/details?id=com.greenmushroom.boomblitz.gp&hl=en_US"
|
||||
|
||||
|
||||
class SoyooLifecyle {
|
||||
|
|
Loading…
Reference in New Issue