构建 NFT 铸造 Dapp 的第一步是准备艺术品。没有艺术品,您就无法实现您的 NFT 项目。
预处理艺术品的另一个原因是为每个图像生成元数据。如果没有此元数据,您的 NFT 将无法在任何大型二级市场(例如 Opensea)上出售。
例如,下图是 Opensea 市场中的 NFT,带有一些元数据,也可以在下面看到。
包括艺术品、细节和特征在内的上述信息可以在下面的 IPFS 图像上看到。
打开您的终端并导航到您的项目目录或在特定位置创建一个项目文件夹。例如,在终端上运行**mkdir preprocessor**
将在您指定的位置创建一个名为“ preprocessor”的文件夹。
接下来,在终端上运行以下命令。
cd preprocessor npm init -y npm install sharp @faker.js/faker --save-dev
上面的命令会在你的项目中安装sharp和faker库。 faker 库将帮助我们生成随机信息。而Sharp库将帮助我们将图像处理成一定的尺寸、质量和格式。
接下来,在您的项目中创建一个名为arts
的文件夹和另一个名为outputs
的文件夹。在“艺术”文件夹中,将所有要处理的图像放入其中。
完成上述步骤后,在“VS code”上打开项目。项目结构应如下所示。
- preprocessor/ - arts/ - node_modules/ - outputs/ - package.json - package-lock.json
太好了,让我们继续编写负责处理图像的引擎。
您需要在计算机上安装以下内容才能完成本教程。
在项目的根目录下创建一个名为**imagify.js**
的文件并粘贴以下代码
const fs = require('fs') const path = require('path') const sharp = require('sharp') const { faker } = require('@faker-js/faker') const input = './arts' const output = './outputs' let img_counter = 1 const imgSize = { width: 500, height: 500 } const desired_ext = '.webp' const base_url = 'https://ipfs.io/ipfs/REPLACE_WITH_IPFS_CID/' const attributes = { weapon: [ 'Stick', 'Knife', 'Blade', 'Clube', 'Ax', 'Sword', 'Spear', 'Gun', 'Craft', ], environment: [ 'Space', 'Sky', 'Desert', 'Forest', 'Grassland', 'Moiuntains', 'Oceans', 'Rainforest', ], rarity: Array.from(Array(10).keys()), } fs.readdirSync(input).forEach((file) => { const orginal_ext = path.extname(file) const orginal_file_name = path.basename(file).split('.')[0] if (['.jpg', '.jpeg', '.png', '.gif', '.webp'].includes(orginal_ext)) { const id = img_counter const metadata = { id, name: `Adulam NFT #${id}`, description: 'AI Arts NFTs Collection, Mint and collect the hottest NFTs around.', price: 1, image: base_url + id + desired_ext, demand: faker.random.numeric({ min: 10, max: 100 }), attributes: [ { trait_type: 'Environment', value: attributes.environment.sort(() => 0.5 - Math.random())[0], }, { trait_type: 'Weapon', value: attributes.weapon.sort(() => 0.5 - Math.random())[0], }, { trait_type: 'Rarity', value: attributes.rarity.sort(() => 0.5 - Math.random())[0], max_value: 10, }, { display_type: 'date', trait_type: 'Created', value: Date.now(), }, { display_type: 'number', trait_type: 'generation', value: 1, }, ], } if (fs.existsSync(`${input}/${orginal_file_name + orginal_ext}`)) { sharp(`${input}/${orginal_file_name + orginal_ext}`) .resize(imgSize.height, imgSize.width) .toFile(`${output}/images/${id + desired_ext}`, (err, info) => console.log(err), ) fs.writeFileSync(`${output}/metadata/${id}.json`, JSON.stringify(metadata), { encoding: 'utf-8', flag: 'w', }) } console.log(metadata) img_counter++ } })
以下步骤将帮助您了解此元数据处理引擎的工作原理。
导入基本库
const fs = require('fs') const path = require('path') const sharp = require('sharp') const { faker } = require('@faker-js/faker') const input = './arts' const output = './outputs'
fs
代表文件系统,它是 NodeJs 附带的内置模块。它负责管理您机器上的文件读写活动。
path
是另一个节点模块,可帮助您浏览机器上的目录结构。这将有助于定位我们的图像保存位置。
Sharp 是我们用于处理图像的模块,例如调整大小和转换为不同的文件类型。
我们将使用 faker 来生成一个随机数。
最后, input
变量包含要处理的图像所在的位置, output
指向将保存处理后的图像的位置。
定义基本变量
let img_counter = 1 const imgSize = { width: 500, height: 500 } const desired_ext = '.webp' const base_url = 'https://ipfs.io/ipfs/REPLACE_WITH_IPFS_CID/' const attributes = { weapon: [ 'Stick', 'Knife', 'Blade', 'Clube', 'Ax', 'Sword', 'Spear', 'Gun', 'Craft', ], environment: [ 'Space', 'Sky', 'Desert', 'Forest', 'Grassland', 'Moiuntains', 'Oceans', 'Rainforest', ], rarity: Array.from(Array(10).keys()), }
上述代码包含在生成元数据过程中使用的重要变量。
**Image_counter**
帮助我们按照当前迭代对图像进行编号。**ImgSize**
定义要处理的每个图像的宽度和高度的尺寸。**Desired_ext**
表示您希望处理后的图像采用的文件格式。**Base_url**
指定要在 IPFS 上存储图像的位置。**Attributes**
包含有关每个图像元数据的更多信息。
执行递归任务
fs.readdirSync(input).forEach((file) => { if(['.jpg', '.jpeg', '.png', '.gif', '.webp'].includes(orginal_ext)) { // Images and metadata tasks are recursively performed here... } })
在上面的代码块中,我们使用文件系统库 (fs) 循环遍历**input**
位置 (arts) 中的所有图像。对于每个图像,我们确保我们的引擎仅从已批准的扩展列表中选择图像。
执行元数据任务
const id = img_counter const metadata = { id, name: `Adulam NFT #${id}`, description: 'AI Arts NFTs Collection, Mint and collect the hottest NFTs around.', price: 1, image: base_url + id + desired_ext, demand: faker.random.numeric({ min: 10, max: 100 }), attributes: [ { trait_type: 'Environment', value: attributes.environment.sort(() => 0.5 - Math.random())[0], }, { trait_type: 'Weapon', value: attributes.weapon.sort(() => 0.5 - Math.random())[0], }, { trait_type: 'Rarity', value: attributes.rarity.sort(() => 0.5 - Math.random())[0], max_value: 10, }, { display_type: 'date', trait_type: 'Created', value: Date.now(), }, { display_type: 'number', trait_type: 'generation', value: 1, }, ], }
在上面的代码块中,我们为每个元数据空间提供了值。例如,环境、武器和所有特征值都是随机动态提供的。
执行图像转换任务
if (fs.existsSync(`${input}/${orginal_file_name + orginal_ext}`)) { sharp(`${input}/${orginal_file_name + orginal_ext}`) .resize(imgSize.height, imgSize.width) .toFile(`${output}/images/${id + desired_ext}`, (err, info) => console.log(err), ) fs.writeFileSync(`${output}/metadata/${id}.json`, JSON.stringify(metadata), { encoding: 'utf-8', flag: 'w', }) } console.log(metadata) img_counter++
在上面的代码片段中,我们再次使用文件系统模块来首先定位我们的每一幅作品并将其调整为我们指定的尺寸(500 x 500)。此外,我们提供了一个与当前迭代一致的新名称,并为其提供了我们想要的扩展名 (webp)。
调整图像大小并将图像转换为webp
极大地优化了我们的艺术作品,达到了惊人的高度。
例如,中,我让这个图像预处理引擎处理了99
张图像,总大小为111MB
。 .png
扩展名的大小下降到62MB
, .webp
扩展名的大小下降到惊人的4.5MB
。如此巨大的尺寸缩减使得使用我的图像构建的 Minting 网站的加载时间有了很大的飞跃。
最后,从上面的代码块中,我们为每个处理的图像创建了JSON
元数据,包含相同的名称和指向图像位置的 URL。此元数据是我们在处理图像后将部署到 IPFS 的内容。
现在,运行下面的命令来转换你的图像。确保您位于项目文件夹中。
node imagify.js
至此,我们完成了我们的图像引擎,我们的输出文件夹应该具有以下文件结构作为结果。
- output/ - images - 1.webp - 2.webp - ...... - metadata - 1.json - 2.json - ......
IPFS 代表行星际文件系统,它是点对点和去中心化的。没有一种简单的方法可以提取存储在 IPFS 上的数据,因此,它是与区块链应用程序一起用于存储媒体内容的近乎完美的对等点。
要使用简单且不易混淆的方式,请前往 IPFS 桌面应用程序安装页面并按照此处指定的说明进行操作。
安装成功后,打开IPFS应用,先上传,我再说一遍,先上传图片文件夹。
将生成一个唯一的 CID(内容标识)字符串作为文件夹名称的一部分,请参见下图。
现在,复制上图中可以看到的图像文件夹 CID,并将其替换到您的**imagify.js**
代码中。请参阅下面的代码。
const base_url = "https://ipfs.io/ipfs/REPLACE_WITH_IPFS_CID/" //old string const base_url = "https://ipfs.io/ipfs/QmY1zrFibpdHQ7qcqZqq7THsqTremZYepXNWR5Au3MF1ST/" //new string
现在,再次运行**node imagify.js**
以将每个图像的准确位置包含到您的JSON元数据中。请参阅替换 CID 前后生成的 JSON 元数据的示例。
您可以观看此视频以了解我如何在完整的 NFT 铸造项目中使用这些图像和元数据。
更换 CID 之前
{ id: 97, name: 'Adulam NFT #97', description: 'AI Arts NFTs Collection, Mint and collect the hottest NFTs around.', price: 1, image: 'https://ipfs.io/ipfs/REPLACE_WITH_IPFS_CID/97.webp', demand: '4', attributes: [ { trait_type: 'Environment', value: 'Forest' }, { trait_type: 'Weapon', value: 'Craft' }, { trait_type: 'Rarity', value: 4, max_value: 10 }, { display_type: 'date', trait_type: 'Created', value: 1664478034024 }, { display_type: 'number', trait_type: 'generation', value: 1 } ] }
更换 CID 后
{ id: 97, name: 'Adulam NFT #97', description: 'AI Arts NFTs Collection, Mint and collect the hottest NFTs around.', price: 1, image: 'https://ipfs.io/ipfs/QmY1zrFibpdHQ7qcqZqq7THsqTremZYepXNWR5Au3MF1ST/97.webp', demand: '7', attributes: [ { trait_type: 'Environment', value: 'Moiuntains' }, { trait_type: 'Weapon', value: 'Clube' }, { trait_type: 'Rarity', value: 2, max_value: 10 }, { display_type: 'date', trait_type: 'Created', value: 1664478110287 }, { display_type: 'number', trait_type: 'generation', value: 1 } ] }
最后,如下图所示,将元数据文件夹与图像文件夹一起上传到 IPFS。
太棒了,现在让我们将它固定在网络上,让全世界都能看到。目前,这两个文件夹都位于您的本地 IPFS 节点(您的计算机)上,要在全球范围内访问它,您需要使用 Pinning 服务,例如Pinata 。
首先,如果您以前没有这样做过,请前往Pinata pin manager并注册。然后单击帐户图标并选择 API 密钥。见下图。
在密钥创建页面上,单击创建新密钥并输入密钥的名称。观察下图。
现在复制剪贴板上的 JWT 密钥。这就是我们将用来将我们的 IPFS 桌面与我们的 Pinata 帐户链接起来的方法。见下图。
接下来,打开您的 IPFS 桌面应用程序,前往设置选项卡并添加新服务,选择 Pinata 并将您的 JWT 令牌粘贴到提供的空间。请参考下图。
最后要做的是使用以下说明将您的文件夹实际固定到 Pinata。
前往文件选项卡,单击三点虚线,然后选择设置固定。这将在下图中弹出。
选择 Pinata 并应用,通过这样做,您的图像文件夹将可以全局访问。
前往该网站,将您的 CID 复制并粘贴到 IPFS 输入字段中,然后单击缓存按钮。这会扫描整个公开可用的 IPFS 网关集以搜索您的图像。见下图。
上图的结果显示,即使您删除了本地节点上的原始副本,许多 IPFS 节点现在都拥有可用且可全局访问的图像文件夹副本。
为您清楚地列出这些步骤后,还可以固定元数据文件夹以使其在线公开可用。
现在,您可以使用上图中的任何链接作为ERC721令牌的基本 URL。见下图。
有了它,这就是如何在 IPFS 上准备和上传你的作品。
您将始终需要了解如何在 IPFS 上批量预处理和上传艺术品。
一旦你了解了如何工作和处理图像到 IPFS,你就可以开始在你的特殊 web3 项目中使用它。
直到下一次,继续粉碎它!
在此处查看我在 Goerli 测试网上的 NFT 项目的现场演示使用情况。请在此处查看 Opensea 的位置。您可以在我的 YouTube 频道上观看视频版本。
我是一名全栈区块链开发人员,在软件开发行业拥有6+
年以上的经验。
通过结合软件开发、写作和教学,我演示了如何在与 EVM 兼容的区块链网络上构建去中心化应用程序。
我的堆栈包括JavaScript
、 React
、 Vue
、 Angular
、 Node
、 React Native
、 NextJs
、 Solidity
等等。
订阅我的 YouTube 频道,了解如何从头开始构建 Web3 应用程序。我还为想要从导师那里一对一学习的认真的人提供私人和专业课程。
现在,让我向您展示如何在代码中表示上述图像和元数据。