Adobe Experience Manager(AEM)Assets には、アセットを処理するためのデフォルトのワークフローとメディアハンドラーのセットが付属しています。ワークフローでは、アセットに対して実行する全般的なタスクを定義し、特定のタスクをメディアハンドラーに委任します。例えば、サムネールの生成やメタデータの抽出などです。
ワークフローは、特定のタイプのアセットがサーバーにアップロードされたときに自動的に実行されるように定義できます。処理手順は、一連の AEM Assets メディアハンドラーに基づいて定義されます。AEM には、組み込みのハンドラーがいくつか用意されています。さらに、追加のハンドラーをカスタムで開発したり、処理をコマンドラインツールに委任して定義したりできます。
メディアハンドラーは、アセットに対して特定の処理を実行する AEM Assets 内のサービスです。例えば、MP3 オーディオファイルを AEM にアップロードすると、ワークフローは MP3 ハンドラーを呼び出し、MP3 ハンドラーはメタデータを抽出してサムネールを生成します。通常、メディアハンドラーはワークフローと組み合わせて使用されます。AEM 内では、よく使用される MIME タイプがサポートされています。アセットに対して特定のタスクを実行するには、ワークフローを拡張または作成するか、メディアハンドラーを拡張または作成するか、メディアハンドラーを無効または有効にします。
注意:
AEM Assets でサポートされるすべての形式と、各形式でサポートされる機能の説明については、Assets でサポートされる形式を参照してください。
ハンドラー名 | サービス名(システムコンソール) | サポートされる MIME タイプ |
TextHandler | com.day.cq.dam.core.impl.handler.TextHandler | text/plain |
PdfHandler | com.day.cq.dam.handler.standard.pdf.PdfHandler | application/pdf |
JpegHandler | com.day.cq.dam.core.impl.handler.JpegHandler | image/jpeg |
Mp3Handler | com.day.cq.dam.handler.standard.mp3.Mp3Handler | audio/mpeg |
ZipHandler | com.day.cq.dam.handler.standard.zip.ZipHandler | application/java-archive application/zip |
PictHandler | com.day.cq.dam.handler.standard.pict.PictHandler | image/pict |
StandardImageHandler | com.day.cq.dam.core.impl.handler.StandardImageHandler | image/gif image/png application/photoshop image/jpeg image/tiff image/x-ms-bmp image/bmp |
MSOfficeHandler | com.day.cq.dam.handler.standard.msoffice.MSOfficeHandler | application/msword |
MSPowerPointHandler | com.day.cq.dam.handler.standard.msoffice.MSPowerPointHandler | application/vnd.ms-powerpoint |
OpenOfficeHandler | com.day.cq.dam.handler.standard.ooxml.OpenOfficeHandler | application/vnd.openxmlformats-officedocument.wordprocessingml.document application/vnd.openxmlformats-officedocument.spreadsheetml.sheet application/vnd.openxmlformats-officedocument.presentationml.presentation |
EPubHandler | com.day.cq.dam.handler.standard.epub.EPubHandler | application/epub+zip |
GenericAssetHandler | com.day.cq.dam.core.impl.handler.GenericAssetHandler | アセットからのデータ抽出用のハンドラーが他に見つからない場合にフォールバックされます |
ブラウザーで、http://localhost:4502/system/console/components.
com.day.cq.dam.core.impl.store.AssetStoreImpl リンクをクリックします。
すべてのアクティブなメディアハンドラーリストが表示されます。次に例を示します。

通常、メディアハンドラーはワークフローと組み合わせて使用されるサービスです。
AEM には、アセットを処理するデフォルトのワークフローがいくつかあります。ワークフローを表示するには、ワークフローコンソールを開き、「モデル」タブをクリックします。「AEM Assets」から始まるワークフロータイトルは、アセット固有のタイトルです。
メディアハンドラーを無効または有効にするには、Apache Felix Web Management Console を使用します。メディアハンドラーを無効にすると、そのアセットに対してメディアハンドラーのタスクは実行されません。
ブラウザーで、http://<host>:<port>/system/console/components に移動します。
メディアハンドラーの名前の横にある「Disable」ボタンをクリックします。例えば com.day.cq.dam.handler.standard.mp3.Mp3Handler です。
ページを更新します。「Disabled」アイコンがメディアハンドラーの横に表示されます。
メディアハンドラーを有効にするには、メディアハンドラーの名前の横にある「Enable」ボタンをクリックします。
実装を開始するための最適な方法は、最も多くの点について対応し、適切なデフォルト動作を提供している付属の抽象実装から継承することです。それが com.day.cq.dam.core.AbstractAssetHandler クラスです。
このクラスには、抽象的なサービス記述子が用意されています。そのため、このクラスから継承し、maven-sling-plugin を使用する場合、inherit フラグを true に設定する必要があります。
以下のメソッドを実装する必要があります。
extractMetadata():使用できるすべてのメタデータを抽出します。
getThumbnailImage():渡されたアセットのサムネール画像を作成します。
getMimeTypes():アセットの MIME タイプを返します。
以下にテンプレート例を示します。
package my.own.stuff; /** * @scr.component inherit="true" * @scr.service */ public class MyMediaHandler extends com.day.cq.dam.core.AbstractAssetHandler { // implement the relevant parts }
インターフェイスとクラスには以下が含まれます。
com.day.cq.dam.api.handler.AssetHandler インターフェイス
- このインターフェイスは、特定の MIME タイプのサポートを追加するサービスを記述します。新しい MIME タイプを追加するには、このインターフェイスを実装する必要があります。このインターフェイスには、特定のドキュメントの読み込みと書き出し、サムネールの作成およびメタデータの抽出をおこなうメソッドがあります。
com.day.cq.dam.core.AbstractAssetHandler クラス
- このクラスは、その他すべてのアセットハンドラー実装の基礎として機能し、よく使用される機能を提供します。
com.day.cq.dam.core.AbstractSubAssetHandler クラス:
- このクラスは、その他すべてのアセットハンドラー実装の基礎として機能し、よく使用される機能を提供します。さらに、サブアセットの抽出についてよく使用される機能も提供します。
- 実装を開始するための最適な方法は、最も多くの点について対応し、適切なデフォルト動作を提供している付属の抽象実装から継承することです。それが com.day.cq.dam.core.AbstractAssetHandler クラスです。
- このクラスには、抽象的なサービス記述子が用意されています。そのため、このクラスから継承し、maven-sling-plugin を使用する場合、inherit フラグを true に設定する必要があります。
以下のメソッドを実装する必要があります。
extractMetadata():使用できるすべてのメタデータを抽出します。
getThumbnailImage():渡されたアセットのサムネール画像を作成します。
getMimeTypes():アセットの MIME タイプを返します。
以下にテンプレート例を示します。
package my.own.stuff; /** * @scr.component inherit="true" * @scr.service */ public class MyMediaHandler extends com.day.cq.dam.core.AbstractAssetHandler { // implement the relevant parts }
インターフェイスとクラスには以下が含まれます。
com.day.cq.dam.api.handler.AssetHandler インターフェイス
- このインターフェイスは、特定の MIME タイプのサポートを追加するサービスを記述します。新しい MIME タイプを追加するには、このインターフェイスを実装する必要があります。このインターフェイスには、特定のドキュメントの読み込みと書き出し、サムネールの作成およびメタデータの抽出をおこなうメソッドがあります。
com.day.cq.dam.core.AbstractAssetHandler クラス
- このクラスは、その他すべてのアセットハンドラー実装の基礎として機能し、よく使用される機能を提供します。
com.day.cq.dam.core.AbstractSubAssetHandler クラス:
このクラスは、その他すべてのアセットハンドラー実装の基礎として機能し、よく使用される機能を提供します。さらに、サブアセットの抽出についてよく使用される機能も提供します。
ここでは、透かしありのサムネールを生成する固有の Text Handler を作成します。
以下の手順を実行します。
Maven プラグインを使用して Eclipse をインストールおよび設定する方法と、Maven プロジェクトに必要な依存関係を設定する方法については、Eclipse での開発環境を設定する方法を参照してください。
以下の手順を実行した後、txt ファイルを AEM にアップロードすると、ファイルのメタデータが抽出され、透かしありの 2 つのサムネールが生成されます。
-
Eclipse で、myBundle Maven プロジェクトを作成します。
メニューバーで、File/New/Other... をクリックして選択します。
ダイアログで、Maven フォルダーを展開し、「Maven Project」を選択して、「Next」をクリックします。
「Create a simple project」と「Use default Workspace locations」の各チェックボックスをオンにして、「Next」をクリックします。
Maven プロジェクトを定義します。
Group Id:com.day.cq5.myhandler
Artifact Id:myBundle
Name:My AEM バンドル
Description:これは AEM バンドルです
「Finish」をクリックします。
-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <!-- ====================================================================== --> <!-- P A R E N T P R O J E C T D E S C R I P T I O N --> <!-- ====================================================================== --> <parent> <groupId>com.day.cq.dam</groupId> <artifactId>dam</artifactId> <version>5.2.14</version> <relativePath>../parent</relativePath> </parent> <!-- ====================================================================== --> <!-- P R O J E C T D E S C R I P T I O N --> <!-- ====================================================================== --> <groupId>com.day.cq5.myhandler</groupId> <artifactId>myBundle</artifactId> <name>My CQ5 bundle</name> <version>0.0.1-SNAPSHOT</version> <description>This is my CQ5 bundle</description> <packaging>bundle</packaging> <!-- ====================================================================== --> <!-- B U I L D D E F I N I T I O N --> <!-- ====================================================================== --> <build> <plugins> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-scr-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.sling</groupId> <artifactId>maven-sling-plugin</artifactId> <configuration> <slingUrlSuffix>/libs/dam/install/</slingUrlSuffix> </configuration> </plugin> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <extensions>true</extensions> <configuration> <instructions> <Bundle-Category>cq5</Bundle-Category> <Export-Package> com.day.cq5.myhandler </Export-Package> </instructions> </configuration> </plugin> </plugins> </build> <!-- ====================================================================== --> <!-- D E P E N D E N C I E S --> <!-- ====================================================================== --> <dependencies> <dependency> <groupId>com.day.cq.dam</groupId> <artifactId>cq-dam-api</artifactId> <version>5.2.10</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.day.cq.dam</groupId> <artifactId>cq-dam-core</artifactId> <version>5.2.10</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.day.cq</groupId> <artifactId>cq-commons</artifactId> </dependency> <dependency> <groupId>javax.jcr</groupId> <artifactId>jcr</artifactId> </dependency> <dependency> <groupId>org.apache.felix</groupId> <artifactId>org.osgi.compendium</artifactId> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> </dependency> <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> </dependency> <dependency> <groupId>com.day.commons</groupId> <artifactId>day-commons-gfx</artifactId> </dependency> <dependency> <groupId>com.day.commons</groupId> <artifactId>day-commons-text</artifactId> </dependency> <dependency> <groupId>com.day.cq.workflow</groupId> <artifactId>cq-workflow-api</artifactId> </dependency> <dependency> <groupId>com.day.cq.wcm</groupId> <artifactId>cq-wcm-foundation</artifactId> <version>5.2.22</version> </dependency> </dependencies>
-
Java クラス MyHandler を作成します。
Eclipse で、myBundle/src/main/java の下の com.day.cq5.myhandler パッケージを右クリックし、「New」、「Class」の順に選択します。
ダイアログウィンドウで、この Java クラスに MyHandler という名前を付け、「Finish」をクリックします。MyHandler.java ファイルが作成され、このファイルが開きます。
MyHandler.java で、既存のコードを以下のコードに置き換えて、変更内容を保存します。
package com.day.cq5.myhandler; import java.awt.Color; import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.jcr.Session; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.day.cq.dam.api.metadata.ExtractedMetadata; import com.day.cq.dam.core.AbstractAssetHandler; import com.day.image.Font; import com.day.image.Layer; import com.day.cq.wcm.foundation.ImageHelper; /** * The <code>MyHandler</code> can extract text files * @scr.component inherit="true" immediate="true" metatype="false" * @scr.service * **/ public class MyHandler extends AbstractAssetHandler { /** * Logger instance for this class. */ private static final Logger log = LoggerFactory.getLogger(MyHandler.class); /** * Music icon margin */ private static final int MARGIN = 10; /** * @see com.day.cq.dam.api.handler.AssetHandler#getMimeTypes() */ public String[] getMimeTypes() { return new String[] {"text/plain"}; } public ExtractedMetadata extractMetadata(Node asset) { ExtractedMetadata extractedMetadata = new ExtractedMetadata(); InputStream data = getInputStream(asset); try { // read text data InputStreamReader reader = new InputStreamReader(data); char[] buffer = new char[4096]; String text = ""; while (reader.read(buffer) != -1) { text += new String(buffer); } reader.close(); long wordCount = this.wordCount(text); extractedMetadata.setProperty("text", text); extractedMetadata.setMetaDataProperty("Word Count",wordCount); setMimetype(extractedMetadata, asset); } catch (Throwable t) { log.error("handling error: " + t.toString(), t); } finally { IOUtils.closeQuietly(data); } return extractedMetadata; } // ----------------------< helpers >---------------------------------------- protected BufferedImage getThumbnailImage(Node node) { ExtractedMetadata metadata = extractMetadata(node); final String text = (String) metadata.getProperty("text"); // create text layer final Layer layer = new Layer(500, 600, Color.WHITE); layer.setPaint(Color.black); Font font = new Font("Arial", 12); String displayText = this.getDisplayText(text, 600, 12); if(displayText!=null && displayText.length() > 0) { // commons-gfx Font class would throw IllegalArgumentException on empty or null text layer.drawText(10, 10, 500, 600, displayText, font, Font.ALIGN_LEFT, 0, 0); } // create watermark and merge with text layer Layer watermarkLayer; try { final Session session = node.getSession(); watermarkLayer = ImageHelper.createLayer(session, "/content/dam/geometrixx/icons/certificate.png"); watermarkLayer.setX(MARGIN); watermarkLayer.setY(MARGIN); layer.merge(watermarkLayer); } catch (RepositoryException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } layer.crop(new Rectangle(510, 600)); return layer.getImage(); } // ---------------< private >----------------------------------------------- /** * This method cuts lines if the text file is too long.. * * @param text * * text to check * * @param height * * text box height (px) * * @param fontheight * * font height (px) * * @return the text which will fit into the box */ private String getDisplayText(String text, int height, int fontheight) { String trimmedText = text.trim(); int numOfLines = height / fontheight; String lines[] = trimmedText.split("\n"); if (lines.length <= numOfLines) { return trimmedText; } else { String cuttetText = ""; for (int i = 0; i < numOfLines; i++) { cuttetText += lines[i] + "\n"; } return cuttetText; } } /** * * This method counts the number of words in a string * * @param text the String whose words would like to be counted * * @return the number of words in the string * */ private long wordCount(String text) { // We need to keep track of the last character, if we have two white spaces in a row we dont want to double count // The starting of the document is always a whitespace boolean prevWhiteSpace = true; boolean currentWhiteSpace = true; char c; long numwords = 0; int j = text.length(); int i = 0; while (i < j) { c = text.charAt(i++); if (c == 0) { break; } currentWhiteSpace = Character.isWhitespace(c); if (currentWhiteSpace && !prevWhiteSpace) { numwords++; } prevWhiteSpace = currentWhiteSpace; } // If we do not end with a white space then we need to add one extra word if (!currentWhiteSpace) { numwords++; } return numwords; } }
AEM を使用すると、ワークフロー内で任意のコマンドラインツールを実行して、アセットを変換し(ImageMagick など)、新しいレンダリングをアセットに追加できます。必要な操作は、AEM サーバーをホストするディスクにコマンドラインツールをインストールし、ワークフローにプロセスのステップを設定することのみです。また、CommandLineProcess という起動プロセスによって、特定の MIME タイプに従ってフィルター処理を実行し、新しいレンダリングに基づいて複数のサムネールを作成することもできます。
以下の変換を自動的に実行し、AEM Assets 内に保存することができます。
- ImageMagick および Ghostscript を使用した EPS および AI 変換
- FFmpeg を使用した FLV ビデオのトランスコーディング
- LAME を使用した MP3 エンコーディング
- SOX を使用したオーディオ処理
注意:
非 Windows システムでは、ファイル名に単一引用符(')を含むビデオアセットのレンダリングの生成中に FFMpeg ツールがエラーを返します。ビデオファイル名に単一引用符が含まれている場合は、AEM にアップロードする前に削除してください。
CommandLineProcess プロセスは、リストに表示されている順序で以下の操作を実行します。
- MIME タイプを指定した場合、そのタイプに従ってファイルをフィルターします。
- AEM サーバーをホストするディスクに一時ディレクトリを作成します。
- 元のファイルを一時ディレクトリにストリーミングします。
- ステップの引数で定義されたコマンドを実行します。AEM を実行しているユーザーの権限を使用して、一時ディレクトリ内でコマンドが実行されます。
- 結果を AEM サーバーのレンダリングフォルダーにストリーミングします。
- 一時ディレクトリを削除します。
- 指定した場合は、それらのレンダリングに基づいてサムネールを作成します。サムネールの数とサイズは、ステップの引数で定義されます。
以下の例は、MIME タイプが gif または tiff のアセットが AEM サーバーの /content/dam に追加されるたびに、元の画像の反転画像と 3 つの追加サムネール(140 x 100、48 x 48 および 10 x 250)が作成されるように、コマンドラインプロセスのステップを設定する方法を示します。
これを実現するには、ImageMagick を使用します。ImageMagick は無料のソフトウェアスイートです。ビットマップ画像の作成、編集および構成をおこなう機能があり、一般的にコマンドラインから使用されます。
まず、AEM サーバーをホストするディスクに ImageMagick をインストールします。
-
ImageMagick をインストールします。詳しくはImageMagick のマニュアルを参照してください。
-
ツールが適切にインストールされているかどうかを確認するには、コマンド convert -h をコマンドラインで実行します。
convert ツールの使用できるすべてのオプションが記載されたヘルプ画面が表示されます。
注意:
Windows のバージョン(Windows SE など)によっては、convert コマンドを実行できない場合があります。このコマンドは、Windows インストールの一部であるネイティブな変換ユーティリティと競合するからです。このような場合は、画像ファイルをサムネールに変換するために使用する ImageMagick ユーティリティの完全パスを指定します。例えば、"C:\Program Files\ImageMagick-6.8.9-Q16\convert.exe" -define jpeg:size=319x319 ${filename} -thumbnail 319x319 cq5dam.thumbnail.319.319.png となります。
引数の形式 | 説明 |
mime:<mime-type> | オプションの引数。アセットの MIME タイプが引数の MIME タイプと同じ場合にプロセスが適用されます。 複数の MIME タイプを定義できます。 |
tn:<width>:<heigth> | オプションの引数。プロセスにより、引数で定義されたサイズのサムネールが作成されます。 複数のサムネールを定義できます。 |
cmd: <command> | 実行するコマンドを定義できます。この構文はコマンドラインツールによって異なります。 定義できるコマンドは 1 つだけです。 コマンドの作成には、以下の変数を使用できます。 ${filename}:入力ファイルの名前(例:original.jpg) |
例えば、AEM サーバーをホストするディスクに ImageMagick がインストールされており、CommandLineProcess を実装として使用し、以下の値をプロセス引数として使用してプロセスのステップを作成するとします。
mime:image/gif,mime:image/tiff,tn:140:100,tn:48:48,tn:10:250,cmd:convert ${directory}/${filename} -flip ${directory}/${basename}.flipped.jpg
この場合、ワークフローを実行すると、MIME タイプが image/gif または mime:image/tiff のアセットにのみ、このステップが適用され、元の画像の反転画像が作成され、.jpg に変換され、140 x 100、48 x 48 および 10 x 250 というサイズの 3 つのサムネールが作成されます。
ImageMagick を使用して 3 つの標準のサムネールを作成するには、以下のプロセス引数を使用します。
mime:image/tiff,mime:image/png,mime:image/bmp,mime:image/gif,mime:image/jpeg,cmd:convert ${filename} -define jpeg:size=319x319 -thumbnail "319x319>" -background transparent -gravity center -extent 319x319 -write png:cq5dam.thumbnail.319.319.png -thumbnail "140x100>" -background transparent -gravity center -extent 140x100 -write cq5dam.thumbnail.140.100.png -thumbnail "48x48>" -background transparent -gravity center -extent 48x48 cq5dam.thumbnail.48.48.png
ImageMagick を使用して Web 対応レンディションを作成するには、以下のプロセス引数を使用します。
mime:image/tiff,mime:image/png,mime:image/bmp,mime:image/gif,mime:image/jpeg,cmd:convert ${filename} -define jpeg:size=1280x1280 -thumbnail "1280x1280>" cq5dam.web.1280.1280.jpeg
注意:
CommandLineProcess ステップは、アセット(ノードタイプ dam:Asset)またはアセットの子孫にのみ適用されます。