I'll come at this from a slightly different direction...
The current price of ETH is ~$1500.
The Yellow Paper states that storing a 256-bit (32-byte) word costs 20,000 gas.
Average gas price is currently ~100 Gwei. That's 100 x 20,000 Gwei per 32 bytes, which is 2,000,000 Gwei, which is 0.002 ETH, which is $3.
1 GB is 1,073,741,824 bytes, so there are 33,554,432 32-byte words. As above, each of these words costs $3, so each GB costs (3 * 33554432) = $100,663,296 at current prices.
5 MB would therefore cost ~$503,316.
Clearly the base cost of an NFT - before any abstract value has been applied - is not the price shown above, so NFT's can't actually be storing the associated picture or movie data on the blockchain.
If you look at the spec for EIP-1155 you'll see it defines an image
field in the token's metadata:
"image": {
"type": "string",
"description": "A URI pointing to a resource with mime type image/* representing the asset to which this token represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive."
},
If we look at a real example, in this case by calling the CryptoKitty (an ERC-721 token) API, we see the following:
-> https://public.api.cryptokitties.co/v1/kitties/1
{
"id": 1,
"name": "Flying Kitten",
"bio": "哎呀妈呀!! 本喵爬不更名,坐不改姓,就叫 #{name}!我的表哥是喵星球鼎鼎大名的多啦A梦。 不是什么太高调的事,不过本喵确实和汤姆猫有过相交之情。 本喵和你是不是上辈子见过呀?",
"image_url": "https://img.cryptokitties.co/0x5328276603d169165d0f71ca67ccc89c45027df3/1.png",
"image_url_cdn": "https://img.cn.cryptokitties.co//0x5328276603d169165d0f71ca67ccc89c45027df3/1.png",
"image_url_png": "https://img.cryptokitties.co/0x5328276603d169165d0f71ca67ccc89c45027df3/1.png",
"image_path": "",
"generation": 0,
And so we see the image files are stored off-chain.
Can we mint 5 gigabyte video NFTs?
Yes, given that they're stored off-chain...
It depends on how you implement your NFT.
In the standard OpenZeppelin implementation, there is no possibility to directly modify the tokenUri
. There's only a getter: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/566a774222707e424896c0c390a84dc3c13bdcb2/contracts/token/ERC721/ERC721.sol#L92
If you think about it, it makes a lot of sense to not allow anyone to modify the uri. If it could be changed, you could sell an NFT which points to uri A and afterwards change it to point to uri B - basically changing the whole NFT contents.
But nothing stops you from adding such extra functionality in the ERC721 contract. It would not be very correct towards users, but technically you can do it - before you deploy the contract. It doesn't make much difference whether the token is already minted or not - you can add functionality to modify whatever you wish.
Best Answer
There's a few ways to do it that I've seen.
All the attributes are stored succinctly into one variable of 256 bits. If you can create a repeatable process to create an image from attributes and you can guarantee that every different valid input creates a separate image then you're good. It is trivial for the smart contract to validate non-duplication. (See CryptoKitties)
You can precalculate all possible images. Then as tokens are minted the guaranteed-unique image is available. The entire set can be committed up-front, even if not publicly known. (Related to CryptoPunks)
As new tokens are minted they do not have any image at all. Then, asynchronously, you will create and publish those images. The smart contract does zero validation here and people must trust you.