some more work ont the video related code, largely related to running on Mac OSX
This commit is contained in:
parent
e6bad87622
commit
ddb7a87e2c
3 changed files with 90 additions and 10 deletions
BIN
photos/salmon.avi
Normal file
BIN
photos/salmon.avi
Normal file
Binary file not shown.
|
|
@ -112,7 +112,7 @@ public class DirectoryEntry extends EntryWithChildren<Entry> {
|
|||
return props;
|
||||
}
|
||||
|
||||
DirectoryProps generateCache() throws IOException {
|
||||
DirectoryProps generateCache() throws IOException, InterruptedException {
|
||||
|
||||
DirectoryProps props = new DirectoryMetadataGenerator(file).generate();
|
||||
db.store(file.getAbsolutePath(), props);
|
||||
|
|
|
|||
|
|
@ -3,9 +3,12 @@ package org.forkalsrud.album.exif;
|
|||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
|
@ -44,7 +47,7 @@ public class DirectoryMetadataGenerator {
|
|||
}
|
||||
|
||||
|
||||
public DirectoryProps generate() throws IOException {
|
||||
public DirectoryProps generate() throws IOException, InterruptedException {
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
DirectoryProps props = new DirectoryProps();
|
||||
|
|
@ -56,7 +59,7 @@ public class DirectoryMetadataGenerator {
|
|||
}
|
||||
|
||||
|
||||
private void generateFileEntries(Properties props) throws IOException {
|
||||
private void generateFileEntries(Properties props) throws IOException, InterruptedException {
|
||||
|
||||
File[] files = dir.listFiles();
|
||||
for (File f : files) {
|
||||
|
|
@ -80,16 +83,30 @@ public class DirectoryMetadataGenerator {
|
|||
continue;
|
||||
}
|
||||
if (name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".JPG")) {
|
||||
String base = "file." + f.getName() + ".";
|
||||
Map<String, String> p = generateThumbnailProperties(f);
|
||||
for (Map.Entry<String, String> e : p.entrySet()) {
|
||||
props.setProperty(base + e.getKey(), e.getValue());
|
||||
}
|
||||
addPropsForFile(props, f, p);
|
||||
} else if (name.endsWith(".MOV") || name.endsWith(".mp4") || name.endsWith(".avi")) {
|
||||
Map<String, String> p = generateVideoProperties(f);
|
||||
addPropsForFile(props, f, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds properties by prefixing each with "file." plus the file name
|
||||
* @param props all props
|
||||
* @param f file (to get the name)
|
||||
* @param p the props to add
|
||||
*/
|
||||
private void addPropsForFile(Properties props, File f, Map<String, String> p) {
|
||||
String base = "file." + f.getName() + ".";
|
||||
for (Map.Entry<String, String> e : p.entrySet()) {
|
||||
props.setProperty(base + e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void generateDirectoryProperties(Properties props, File f) {
|
||||
|
||||
String name = f.getName();
|
||||
|
|
@ -167,20 +184,82 @@ public class DirectoryMetadataGenerator {
|
|||
return props;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The crazy Mac OSX does not even set the PATH to a reasonable value, so
|
||||
* we have to jump through hoops to guess where we may find the executables
|
||||
* for mplayer and friends.
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
private String findExecutableInShellPath(String name) throws IOException, InterruptedException {
|
||||
|
||||
String executableForName = name;
|
||||
ProcessBuilder pb = new ProcessBuilder(Arrays.asList(System.getenv("SHELL")));
|
||||
pb.redirectErrorStream(true); // send errors to stdout
|
||||
Process p = pb.start();
|
||||
PrintStream stdin = new PrintStream(p.getOutputStream());
|
||||
stdin.print("echo $PATH"); // This is still not entirely portable. Windows would like %PATH%
|
||||
stdin.close();
|
||||
InputStream stdout = p.getInputStream();
|
||||
String searchPath = IOUtils.toString(stdout);
|
||||
int returnStatus = p.waitFor();
|
||||
|
||||
String separator = System.getProperty("path.separator");
|
||||
if (searchPath != null && separator != null && !"".equals(separator)) {
|
||||
String[] elements = searchPath.split(separator);
|
||||
for (String path : elements) {
|
||||
|
||||
File executable = new File(path, name);
|
||||
if (executable.isFile()) {
|
||||
executableForName = executable.getAbsolutePath();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return executableForName;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Transcoding probably needs to go in at some point.
|
||||
* A suitable command line may be like the one below, as suggested by
|
||||
* http://rob.opendot.cl/index.php/useful-stuff/ffmpeg-x264-encoding-guide/
|
||||
* http://rob.opendot.cl/index.php/useful-stuff/encoding-a-flv-video-for-embedded-web-playback/
|
||||
*
|
||||
* Assuming video in is 1280x720 pixels resolution and we want to show 640x360
|
||||
* and we want an output bitrate about 1 Mbit/sec
|
||||
* we can do a one pass encoding like this:
|
||||
*
|
||||
* ffmpeg -i <infile> -aspect 1280:720 -s 640x360 -b 1000000 -crf 25 \
|
||||
* -vcodec libx264 -vpre knut_low \
|
||||
* -acodec libfaac -aq 100 \
|
||||
* <outfile>.mp4
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param f the jpeg file
|
||||
* @param f the movie file
|
||||
* @return a map with the following keys: orientation dimensions captureDate comment etag
|
||||
* @throws IOException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
private Map<String, String> generateVideoProperties(File f) throws IOException {
|
||||
private Map<String, String> generateVideoProperties(File f) throws IOException, InterruptedException {
|
||||
|
||||
String mplayerExecutable = findExecutableInShellPath("mplayer");
|
||||
|
||||
Map<String, String> props = new HashMap<String, String>();
|
||||
ProcessBuilder pb = new ProcessBuilder().command(
|
||||
"mplayer", "-vo", "null", "-ao", "null", "-frames", "0", "-identify", f.getAbsolutePath());
|
||||
mplayerExecutable, "-vo", "null", "-ao", "null", "-frames", "0", "-identify", f.getAbsolutePath());
|
||||
pb.redirectErrorStream(false);
|
||||
Process p = pb.start();
|
||||
p.getOutputStream().close();
|
||||
List<String> lines = IOUtils.readLines(p.getInputStream());
|
||||
int returnStatus = p.waitFor();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HHmmss");
|
||||
String width = "", height = "";
|
||||
for (String line : lines) {
|
||||
|
|
@ -192,6 +271,7 @@ public class DirectoryMetadataGenerator {
|
|||
if (name.equals("ID_VIDEO_HEIGHT")) height = value;
|
||||
}
|
||||
}
|
||||
props.put("type", "movie");
|
||||
props.put("orientation", "1");
|
||||
props.put("dimensions", new Dimension(width, height).toString());
|
||||
props.put("captureDate", sdf.format(new Date(f.lastModified())));
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue