Wp media regenerate --yes not working for PDF files

Issue Summary

I’m struggling to regenerate PDF thumbnails from the command line.

Replication

I right click the site I am using and click Open site shell

I’m using the following command:

$ wp media regenerate --yes

This gives me the following error:

**Warning:** PostscriptDelegateFailed `[ghostscript library 9.53] -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 '-sDEVICE=pngalpha' -dTextAlphaBits=4 -dGraphicsAlphaBits=4 '-r128x128' -dFirstPage=1 -dLastPage=1 '-sOutputFile=/var/folders/y9/5xfvdhfs5f9b84y8qrrc6wfw0000gn/T/magick-lM-cuhktyHh3psfV5_8R7-ID-GpJwtex%d' '-f/var/folders/y9/5xfvdhfs5f9b84y8qrrc6wfw0000gn/T/magick-QUKvaVdN826GAm_U8Zy25F3sZIQCUyfd' '-f/var/folders/y9/5xfvdhfs5f9b84y8qrrc6wfw0000gn/T/magick-9HycecRNcmbWGY-_bhE083q6IROaQ831'': GPL Ghostscript 9.53.3: Can't find initialization file gs_init.ps.
@ error/ghostscript-private.h/InvokeGhostscriptDelegate/178 (ID 33733)
**Warning:** No metadata. (ID 33733)
1/8 Couldn't regenerate thumbnails for "Detective-Digiduck—150" (ID 33733).

Just for clarity, the line at the very end of that says:

Can't find initialization file gs_init.ps.

I have tried taking the advice here and brew installing Ghostscript:
c# - Can't find initialization file gs_init.ps - Stack Overflow but this doesn’t seem to change the issue.

It is confusing as if I manually upload the PDF file into WordPress, the image is generated nicely. It is only in the command line that the error occurs. Is there another way to SSH into the Local Box and have use exactly the same environment as the WordPress install? Clearly everything is working if it can do it in the admin panels.

Regular images work well.

System Details

  • 6.1.2

  • MacOS BigSur

Thanks for any help / pointers!

PS I am automating the upload of several thousand PDF files so am unable to just manually import each one.

What version of PHP is being used on the site?

I’m not able to generate a preview of a PDF file even in the wp-admin, but I think that’s because of this bug related to Imagick in Local’s PHP lightning services:

The confusing part to me is that the error you mention references ghostscript which I think Imagick uses if present, so that makes me think that at least some of Imagick is working for you on your machine.

Thanks for looking into this, Ben. I had to change the PHP version to 7.4.1 in Local to make the image previews generate. It was after changing to this version I realised that they weren’t generated over the cli.

If I bump it to version 8.0.0 I get another error:

Failed loading /Users/djave_co/Library/Application Support/Local/lightning-services/php-8.0.0+2/bin/darwin/lib/php/extensions/no-debug-non-zts-20200930/opcache.so: dlopen(/Users/djave_co/Library/Application Support/Local/lightning-services/php-8.0.0+2/bin/darwin/lib/php/extensions/no-debug-non-zts-20200930/opcache.so, 9): Symbol not found: _zend_cannot_pass_by_reference

Referenced from: /Users/djave_co/Library/Application Support/Local/lightning-services/php-8.0.0+2/bin/darwin/lib/php/extensions/no-debug-non-zts-20200930/opcache.so

Expected in: flat namespace

in /Users/djave_co/Library/Application Support/Local/lightning-services/php-8.0.0+2/bin/darwin/lib/php/extensions/no-debug-non-zts-20200930/opcache.so

Xdebug requires Zend Engine API version 420200930.

The Zend Engine API version 320190902 which is installed, is outdated.
Found 8 images to regenerate.
1/8 Skipped thumbnail regeneration for "Detective-Digiduck—150" (ID 33733).
2/8 Skipped thumbnail regeneration for "Ditectif-Digihwyaden" (ID 33727).
3/8 Skipped thumbnail regeneration for "Detective-Digiduck—150" (ID 33726).
4/8 Regenerated thumbnails for "thumbnail2" (ID 33725).
5/8 Regenerated thumbnails for "DLs_hero_image_no_quote_FINAL" (ID 33724).
6/8 Regenerated thumbnails for "4_stats" (ID 33723).
7/8 Regenerated thumbnails for "thumbnail2" (ID 33722).
8/8 Regenerated thumbnails for "thumbnail2" (ID 33721).

The successful generations are only images, not PDFs.

Thanks for that push in the right direction! The good news is, I was able to replicate what you’re seeing on PHP 7.4.1 as well as PHP 8.0!

The less-good news is that I’m not 100% sure why that’s the case since that gs_init.ps file does exist. I was thinking that maybe the system installed version of Ghostscript was being used, but even temporarily renaming the gs binary didn’t help.

If I were to guess, it might be that the space in the path of .../Application Support/... is causing issues. Either way, I’m not sure how quickly, or even if it’s possible that this sort of thing can be fixed.

I think that in order to get you unblocked, you have one of two options:

  1. Deploy the site somewhere under an actual Linux environment and try running the wpcli script again
  2. Temporarily install this plugin to regenerate those thumbs within the wp-admin: Regenerate Thumbnails – WordPress plugin | WordPress.org

Thanks for looking into it. I found the Regenerate Thumbnails plugin wouldn’t work if the PDFs were already present in WordPress with no images.

For my project, it is an automated node importer for a project that is going live quite soon so it wasn’t possible to wait. I found a pretty horrible work around I had to do for each PDF file, maybe it might help someone in future.

// CreatePDFThumbnail.js
import shell from "shelljs";
import config from "../config.js";

export default async (id, pdfPath, title) => {
	shell.cd(config.wpInstall, { silent: true });

	let jpgName = pdfPath.split("/").pop().replace(".pdf", "-thumbnail.jpg");
	let jpgPath = `~/temp-files/${jpgName}`;

    // Manually create the jpg thumbnail
	let command = `gs -o ${jpgPath} -sDEVICE=jpeg -dLastPage=1 ${pdfPath}`;
	let createJpg = shell.exec(command);

    // Find the size of the original image (again, imagemagik isn't really an option)
	let getSize = shell.exec(`file ${jpgPath}`);
	const sizeRegex = /, (\d+)x(\d+),/gm;
	var reg = sizeRegex.exec(getSize.stdout);
	const width = reg[1];
	const height = reg[2];
	console.log({ width, height });

    // Import it, and capture the ID
	command = `wp media import ${jpgPath} --post_id=${id} --title="${title} thumb" --porcelain`;
	let output = shell.exec(command);
	let uploadId = output.stdout.trim();
	console.log({ uploadId });

    // When the thumbnail is uploaded, the metadata created is nearly what we want for the PDF thumb
	command = `wp post get ${uploadId} --fields=guid`;
	let postCommand = shell.exec(command);
	let file = postCommand.stdout
		.split("\n")
		.filter((line) => line.indexOf(".jpg") >= 0)
		.map((line) => line.split("\t")[1])[0]
		.split("/")
		.pop();
	command = `wp post meta get ${uploadId} _wp_attachment_metadata --format=json`;
	let metadata = shell.exec(command, { silent: true });
	metadata = JSON.parse(metadata.trim());

    // However there are a few bits we don't need
	delete metadata.image_meta;
	delete metadata.file;
	delete metadata.width;
	delete metadata.height;

    // and its missing the all important full size image
	metadata.sizes.full = {
		height,
		width,
		file,
		"mime-type": metadata.sizes.thumbnail["mime-type"],
	};
	console.log(metadata);

    // Now we can set the metadata of the PDF file, using what we got from the jpg
	console.log(`Setting meta data for ${id}`);
	command = `wp post meta update ${id} _wp_attachment_metadata ${JSON.stringify(
		JSON.stringify(metadata)
	)} --format=json`;
	console.log(command);
	let updatedata = shell.exec(command);

    // And finally delete the records from the thumbnail in the database (all record data is stored with the PDF now)
	let postsQuery = `wp db query "DELETE FROM \"wp_posts\" WHERE \"id\" = ${uploadId};" --socket="~/Library/Application Support/Local/run/Ri0gz2LNO/mysql/mysqld.sock"`;
	let metaQuery = `wp db query "DELETE FROM \"wp_postmeta\" WHERE \"post_id\" = ${uploadId};" --socket="~/Library/Application Support/Local/run/Ri0gz2LNO/mysql/mysqld.sock"`;

	shell.exec(postsQuery);
	shell.exec(metaQuery);

	return true;
};
1 Like

Oof. I’m sorry you had to write that, but it does make me smile to see the creative ways that devs figure out how to do something to get the job done!

Thanks for sharing your solution!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.