Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.sms.server.service.parser; import com.sms.server.domain.MediaElement; import com.sms.server.domain.MediaElement.MediaElementType; import com.sms.server.service.LogService; import com.sms.server.service.TranscodeService; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * * @author scott2ware */ @Service public class MetadataParser { private static final String CLASS_NAME = "MetadataParser"; // Patterns private static final Pattern TITLE = Pattern.compile("^title\\s*:\\s+(.+)", Pattern.CASE_INSENSITIVE); private static final Pattern ARTIST = Pattern.compile("^(artist|band)\\s*:\\s+(.+)", Pattern.CASE_INSENSITIVE); private static final Pattern ALBUMARTIST = Pattern.compile("^album(\\s|_)artist\\s*:\\s+(.+)", Pattern.CASE_INSENSITIVE); private static final Pattern ALBUM = Pattern.compile("^album\\s*:\\s+(.+)", Pattern.CASE_INSENSITIVE); private static final Pattern COMMENT = Pattern.compile("^comment\\s*:\\s+(.+)", Pattern.CASE_INSENSITIVE); private static final Pattern GENRE = Pattern.compile("^genre\\s*:\\s+(.+)", Pattern.CASE_INSENSITIVE); private static final Pattern YEAR = Pattern.compile("^(date|tyer|year)\\s*:\\s+(\\d{4})", Pattern.CASE_INSENSITIVE); private static final Pattern DISCNUMBER = Pattern.compile("^(disc|discnumber)\\s*:\\s+(\\d+)", Pattern.CASE_INSENSITIVE); private static final Pattern DISCSUBTITLE = Pattern.compile("^discsubtitle\\s*:\\s+(.+)", Pattern.CASE_INSENSITIVE); private static final Pattern TRACK = Pattern.compile("^track\\s*:\\s+(\\d+)", Pattern.CASE_INSENSITIVE); private static final Pattern BITRATE = Pattern.compile("bitrate:\\s+(\\d+)\\s+kb/s"); private static final Pattern DURATION = Pattern.compile("Duration:\\s+(\\d+):(\\d+):(\\d+).(\\d+),"); private static final Pattern AUDIO_STREAM = Pattern .compile("Stream.*?([(](.+)[)])?:\\s+Audio:\\s*(\\S+).*?,\\s*(\\d+)\\s+Hz,\\s*([\\w\\.]+)"); private static final Pattern VIDEO_STREAM = Pattern .compile("Stream.*?:\\s+Video:\\s*(\\S+).*?,\\s+(\\d+)x(\\d+)"); private static final Pattern SUBTITLE_STREAM = Pattern .compile("Stream.*?([(](.+)[)])?:\\s+Subtitle:\\s*([^,\\s]+).*?([(]forced[)])?$"); @Autowired private TranscodeService transcodeService; public MediaElement parse(MediaElement mediaElement) { try { // Use transcoder to parse file metadata File parser = transcodeService.getTranscoder(); String[] command = new String[] { parser.getAbsolutePath(), "-i", mediaElement.getPath() }; ProcessBuilder processBuilder = new ProcessBuilder(command).redirectErrorStream(true); Process process = processBuilder.start(); String[] metadata = readInputStream(process.getInputStream()); // Get Media Type Byte mediaType = mediaElement.getType(); // Begin Parsing for (String line : metadata) { Matcher matcher; if (mediaType == MediaElementType.AUDIO || mediaType == MediaElementType.VIDEO) { // // Duration // matcher = DURATION.matcher(line); if (matcher.find()) { int hours = Integer.parseInt(matcher.group(1)); int minutes = Integer.parseInt(matcher.group(2)); int seconds = Integer.parseInt(matcher.group(3)); mediaElement.setDuration(hours * 3600 + minutes * 60 + seconds); } // // Bitrate // matcher = BITRATE.matcher(line); if (matcher.find()) { mediaElement.setBitrate(Integer.parseInt(matcher.group(1))); } // // Audio Stream // matcher = AUDIO_STREAM.matcher(line); if (matcher.find()) { // Language // Always set audio language for video elements if (matcher.group(1) == null && mediaType == MediaElementType.VIDEO) { mediaElement.setAudioLanguage( addToCommaSeparatedList(mediaElement.getAudioLanguage(), "und")); } // Set audio language if present if (matcher.group(1) != null) { mediaElement.setAudioLanguage(addToCommaSeparatedList(mediaElement.getAudioLanguage(), String.valueOf(matcher.group(2)))); } // Codec mediaElement.setAudioCodec(addToCommaSeparatedList(mediaElement.getAudioCodec(), String.valueOf(matcher.group(3)))); //Sample Rate mediaElement.setAudioSampleRate(addToCommaSeparatedList(mediaElement.getAudioSampleRate(), String.valueOf(matcher.group(4)))); //Configuration mediaElement.setAudioConfiguration(addToCommaSeparatedList( mediaElement.getAudioConfiguration(), String.valueOf(matcher.group(5)))); } } if (mediaType == MediaElementType.AUDIO) { // // Title // matcher = TITLE.matcher(line); if (matcher.find()) { mediaElement.setTitle(String.valueOf(matcher.group(1))); } // // Artist // matcher = ARTIST.matcher(line); if (matcher.find()) { mediaElement.setArtist(String.valueOf(matcher.group(2))); } // // Album Artist // matcher = ALBUMARTIST.matcher(line); if (matcher.find()) { mediaElement.setAlbumArtist(String.valueOf(matcher.group(2))); } // // Album // matcher = ALBUM.matcher(line); if (matcher.find()) { mediaElement.setAlbum(String.valueOf(matcher.group(1))); } // // Comment // matcher = COMMENT.matcher(line); if (matcher.find()) { mediaElement.setDescription(String.valueOf(matcher.group(1))); } // // Date // matcher = YEAR.matcher(line); if (matcher.find()) { mediaElement.setYear(Short.parseShort(matcher.group(2))); } // // Disc Number // matcher = DISCNUMBER.matcher(line); if (matcher.find()) { mediaElement.setDiscNumber(Byte.parseByte(matcher.group(2))); } // // Disc Subtitle // matcher = DISCSUBTITLE.matcher(line); if (matcher.find()) { mediaElement.setDiscSubtitle(String.valueOf(matcher.group(1))); } // // Track Number // matcher = TRACK.matcher(line); if (matcher.find()) { mediaElement.setTrackNumber(Short.parseShort(matcher.group(1))); } // // Genre // matcher = GENRE.matcher(line); if (matcher.find()) { mediaElement.setGenre(String.valueOf(matcher.group(1))); } } if (mediaType == MediaElementType.VIDEO) { // // Video Stream // matcher = VIDEO_STREAM.matcher(line); // Only pull metadata for the first video stream (embedded images are also detected as video...) if (matcher.find() && mediaElement.getVideoCodec() == null) { // Codec mediaElement.setVideoCodec(String.valueOf(matcher.group(1))); // Dimensions short width = Short.parseShort(matcher.group(2)); short height = Short.parseShort(matcher.group(3)); if (width > 0 && height > 0) { mediaElement.setVideoWidth(width); mediaElement.setVideoHeight(height); } } // // Subtitle Stream // matcher = SUBTITLE_STREAM.matcher(line); if (matcher.find()) { // Language if (matcher.group(1) == null) { mediaElement.setSubtitleLanguage( addToCommaSeparatedList(mediaElement.getSubtitleLanguage(), "und")); } else { mediaElement.setSubtitleLanguage(addToCommaSeparatedList( mediaElement.getSubtitleLanguage(), String.valueOf(matcher.group(2)))); } // Format mediaElement.setSubtitleFormat(addToCommaSeparatedList(mediaElement.getSubtitleFormat(), String.valueOf(matcher.group(3)))); //Forced if (matcher.group(4) == null) { mediaElement.setSubtitleForced( addToCommaSeparatedList(mediaElement.getSubtitleForced(), "false")); } else { mediaElement.setSubtitleForced( addToCommaSeparatedList(mediaElement.getSubtitleForced(), "true")); } } } } } catch (IOException x) { LogService.getInstance().addLogEntry(LogService.Level.ERROR, CLASS_NAME, "Unable to parse metadata for file " + mediaElement.getPath(), x); } return mediaElement; } private String[] readInputStream(InputStream input) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(input)); List<String> result = new ArrayList<>(); String line; while ((line = reader.readLine()) != null) { line = line.trim(); if (line.length() > 0) { result.add(line); } } // Close streams input.close(); reader.close(); return result.toArray(new String[result.size()]); } private String addToCommaSeparatedList(String list, String entryToAdd) { if (entryToAdd == null) { return list; } else if (entryToAdd.equals("")) { return list; } if (list == null) { list = entryToAdd; } else if (list.equals("")) { list = entryToAdd; } else { list = list + "," + entryToAdd; } return list; } }