I'd create a general table for any type of content:
CREATE TABLE ProductContents(
content_id INT AUTO_INCREMENT PRIMARY KEY,
content_type INT NOT NULL
-- other general attributes like when it was created, by whom, etc.
);
For each text, image, or video, insert one row into this table. If you use an auto-increment primary key, this table is responsible for generating the id number.
For tags, now you simply have a many-to-many relationship between ProductContent and Tags. This is represented by an intersection table.
CREATE TABLE Tags (
tag_id INT AUTO_INCREMENT PRIMARY KEY,
tag TEXT NOT NULL
);
CREATE TABLE ProductContentTagged (
content_id INT,
tag_id INT,
PRIMARY KEY (content_id, tag_id),
FOREIGN KEY (content_id) REFERENCES ProductContents(content_id),
FOREIGN KEY (tag_id) REFERENCES Tags(tag_id),
);
Then if you have any attributes specific to each type of content, create auxiliary tables for each type, with a one-to-one relationship to the content table.
CREATE TABLE ProductContentTexts (
content_id INT PRIMARY KEY,
content TEXT NOT NULL,
FOREIGN KEY (content_id) REFERENCES ProductContents(content_id)
);
CREATE TABLE ProductContentImages (
content_id INT PRIMARY KEY,
image_path TEXT NOT NULL,
FOREIGN KEY (content_id) REFERENCES ProductContents(content_id)
);
CREATE TABLE ProductContentVideos (
content_id INT PRIMARY KEY,
video_path TEXT NOT NULL,
FOREIGN KEY (content_id) REFERENCES ProductContents(content_id)
);
Note these auxiliary tables don't have an auto-increment column. They don't need to -- they will always use the value that was generated by the ProductContents table, and you're responsible for inserting that value.