워드프레스 애니메이션 gif 파일을 mp4로 변환하여 출력하기

최근에 애니메이션 gif 파일을 mp4로 변경해서 출력하는 게 유행(?)이라고 할까? 포스팅 때 애니메이션 gif 파일을 첨부하지는 않기 때문에 굳이 관심을 가져야 할 이유가 없었는데.. 오늘은 왠지 한번 해볼까? 하는 생각이 들어서 기본 기능만 작동하도록 플러그인을 만들어 봤다. 개발 환경은 아래와 같다.
- WordPress : 5.5
- PHP : 7.4.9
- ffmpeg : 4.2.4
gif 파일을 mp4 및 webm 파일로 변경하는 코드는 아래와 같다. 이 파일을 functions.php
파일로 저장한다.
<?php
// https://www.php.net/manual/en/function.imagecreatefromgif.php#104473
function isAnimatedGIF($gif) {
if(!($fh = @fopen($gif, 'rb')))
return false;
$count = 0;
//an animated gif contains multiple "frames", with each frame having a
//header made up of:
// * a static 4-byte sequence (\x00\x21\xF9\x04)
// * 4 variable bytes
// * a static 2-byte sequence (\x00\x2C) (some variants may use \x00\x21 ?)
// We read through the file til we reach the end of the file, or we've found
// at least 2 frame headers
while(!feof($fh) && $count < 2) {
$chunk = fread($fh, 1024 * 100); //read 100kb at a time
$count += preg_match_all('#\x00\x21\xF9\x04.{4}\x00(\x2C|\x21)#s', $chunk, $matches);
}
fclose($fh);
return $count > 1;
}
function convert_gif2mp4($content)
{
$images = array();
$upload_info = wp_upload_dir();
$upload_dir = $upload_info['basedir'];
$upload_url = $upload_info['baseurl'];
$pattern = '#<img[^>]*src=[\'"]?(.+\.gif)[\'"]?[^>]*>#i';
preg_match_all($pattern, $content, $matches);
$count = count($matches[1]);
$urls = array();
if ( $count > 0 ) {
for ( $i=0; $i<$count; $i++ ) {
$url = $matches[1][$i];
$url2 = preg_replace('#^https?:#i', '', $url);
if(in_array($url2, $urls))
continue;
$urls[] = $url;
// 로컬 파일인지 체크
if(strpos( $url, $upload_url ) === false)
continue;
// 이미지 경로 설정
$rel_path = str_replace( $upload_url, '', $url);
$img_file = $upload_dir . $rel_path;
// gif 파일인지 체크
if( !is_file($img_file))
continue;
$size = @getimagesize($img_file);
if($size[2] != 1)
continue;
// 애니메이션 gif 체크
if (!isAnimatedGIF($img_file))
continue;
// mp4 파일 생성
$pinfo = pathinfo($img_file);
$mp4 = $pinfo['dirname'].'/'.$pinfo['filename'].'.mp4';
$webm = $pinfo['dirname'].'/'.$pinfo['filename'].'.webm';
$poster = $pinfo['dirname'].'/poster_'.$pinfo['filename'].'.jpg';
if (is_writable($pinfo['dirname']) && !is_file($mp4)) {
try {
$poster = $pinfo['dirname'].'/poster_'.$pinfo['filename'].'.jpg';
$image = @imagecreatefromgif($img_file);
imagejpeg($image, $poster, 90);
@exec('ffmpeg -i '.escapeshellcmd(preg_replace('/[^0-9A-Za-z_\-\.\\\\\/]/i', '', $img_file)).' -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" -c:v libx264 -pix_fmt yuv420p -movflags +faststart '.escapeshellcmd(preg_replace('/[^0-9A-Za-z_\-\.\\\\\/]/i', '', $mp4)));
@exec('ffmpeg -i '.escapeshellcmd(preg_replace('/[^0-9A-Za-z_\-\.\\\\\/]/i', '', $img_file)).' -c vp9 -b:v 0 -crf 41 '.escapeshellcmd(preg_replace('/[^0-9A-Za-z_\-\.\\\\\/]/i', '', $webm)));
} catch(Exception $e) {
continue;
}
}
if (is_file($mp4)) {
$video = '<video poster="'.str_replace($upload_dir, $upload_url, $poster).'" autoplay="autoplay" loop="loop" preload="auto" playsinline webkit-playsinline muted>';
if (is_file($webm))
$video .= '<source src="'.str_replace($upload_dir, $upload_url, $webm).'" type="video/webm">';
$video .= '<source src="'.str_replace($upload_dir, $upload_url, $mp4).'" type="video/mp4">';
$video .= '</video>';
$content = str_replace($matches[0][$i], $video, $content);
}
}
}
return $content;
}
워드프레스 플러그인 적용을 위한 gif2mp4.php
파일은 아래와 같다.
<?php
/**
* @package Convert GIF to MP4 in Post
* @version 1.0.0
*/
/*
Plugin Name: Convert GIF to MP4 in Post
Plugin URI: https://chicpro.dev/
Description: This plugin animated gif to mp4 using ffmpeg in post.
Author: chicpro
Version: 1.0.0
Author URI: https://chicpro.dev/
*/
require ( plugin_dir_path( __FILE__ ) . '/functions.php' );
add_filter ('the_content', 'convert_gif2mp4', 100);
위 두개의 파일을 wp-content > plugins 폴더 안에 gif2mp4 와같은 폴더를 생성한 후 그 안에 넣어준다. 그런 다음 워드프레스 관리자 페이지에서 플러그인을 활성해 주면 된다. 포스트 내용에 gif 파일이 출력되는 코드에 따라 $pattern = '#<img[^>]*src=[\'"]?(.+\.gif)[\'"]?[^>]*>#i';
이 부분을 적당히 수정해야 할 수도 있다. 전체 코드는 github 에서 다운로드 할 수 있다.
github repo : https://github.com/chicpro/wordpress-gif2mp4

완전 좋아요!
mp4와 webm을 동시에 지원하는 개념이 정말 좋은 것 같습니다.
선택해서 보여주는 걸까요?
아마 기기에 따라서 선택되어 재생이 될 것으로 생각됩니다.
외국 쪽 자료에서는 mp4와 webm을 동시에 지원하는 게 많습니다.
혹시 그누보드도 가능할까요?
이미 thisgun님의 https://sir.kr/g5_plugin/7476 플러그인도 있지만
webm은 지원이 안더라구요.
그누보드에서 webm까지 한꺼번에 지원되면 정말 좋을 것 같습니다.
어떤 부분을 바꾸면 될까요?
요즘 그누보드 작업이 별로 없어서요.. ^^;
근데.. 이미 수정하신 것 같네요. ㅎㅎ
참고해서 그누보드 5.4용 플러그인을 수정해보았습니다.
그런데 출력할 때
if (is_file($webm))
이 부분은 그누보드에서 어떻게 처리해야될지 모르겠습니다.
일단 그냥 if 부분없이 다 출력되도록 했거든요.
그러니 정상적으로 소스에 webm과 mp4가 둘다 들어갔습니다.
if webm 부분은 왜 넣었을까요?
gif 중에 webm 생성이 안되는 파일이 있는건가요?
음.. 저는 거의 습관적으로 파일 유무를 체크하는 것 같습니다.
테스트 중 webm 파일이 생성되지 않은 경우는 없지만..
오류라는 건 언제 발생할지 모르니까요..
일단 webm과 mp4를 동시에 출력이 되게 설정했습니다.
플러그인을 수정해서 그누보드 플러그인에 올려도 되겠죠? ^^;;;
감사합니다.
제 코드가 조금이라도 도움이 됐다면.. 그걸로 만족합니다. 감사합니다.
안녕하세요 소중한 자료 감사합니다
다름이 아니라 제가 word press 에서 귀하의 파일 적용해서 잘 테스트 하고,
갑자기 서버 이전할 일이 생겨 백업 후 서버 옮겼더니 안되네요….
전 서버에서는 잘 되었는데,,, 혹시 권한 문제인거 같기도 한데
퍼미션 설정을 제가 놓친게 있을까요
아니면 제가 뭔가 큰 걸 놓치고 있는걸까요 ㅠㅠ
고견 기다립니다
안녕하세요.
먼저 확인해 보셔야할 것이 ffmpeg 패키지가 설치되어 있는지.. php 에서 exec 명령어는 사용이 가능한지 등 입니다. ffmpeg 등이 설치되어 있는데도 파일이 생성되지 않는다면 퍼미션 부분일텐데요.. 쓰기 권한이 있는지 확인해 보셔야할 것으로 생각됩니다.