mirror of
https://github.com/airsonic/airsonic.git
synced 2025-10-03 17:59:25 +02:00
Removed separate audio downsampling
My guess is that this probably resolves #624.
This commit is contained in:
parent
453f00232d
commit
994c1d61ed
9 changed files with 50 additions and 74 deletions
|
@ -99,7 +99,7 @@ public class PlayerSettingsController {
|
||||||
command.setActiveTranscodingIds(activeTranscodingIds);
|
command.setActiveTranscodingIds(activeTranscodingIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
command.setTranscodingSupported(transcodingService.isDownsamplingSupported(null));
|
command.setTranscodingSupported(transcodingService.isTranscodingSupported(null));
|
||||||
command.setTranscodeDirectory(transcodingService.getTranscodeDirectory().getPath());
|
command.setTranscodeDirectory(transcodingService.getTranscodeDirectory().getPath());
|
||||||
command.setTranscodeSchemes(TranscodeScheme.values());
|
command.setTranscodeSchemes(TranscodeScheme.values());
|
||||||
command.setTechnologies(PlayerTechnology.values());
|
command.setTechnologies(PlayerTechnology.values());
|
||||||
|
|
|
@ -57,7 +57,6 @@ public class TranscodingSettingsController {
|
||||||
|
|
||||||
map.put("transcodings", transcodingService.getAllTranscodings());
|
map.put("transcodings", transcodingService.getAllTranscodings());
|
||||||
map.put("transcodeDirectory", transcodingService.getTranscodeDirectory());
|
map.put("transcodeDirectory", transcodingService.getTranscodeDirectory());
|
||||||
map.put("downsampleCommand", settingsService.getDownsamplingCommand());
|
|
||||||
map.put("hlsCommand", settingsService.getHlsCommand());
|
map.put("hlsCommand", settingsService.getHlsCommand());
|
||||||
map.put("brand", settingsService.getBrand());
|
map.put("brand", settingsService.getBrand());
|
||||||
|
|
||||||
|
@ -133,7 +132,6 @@ public class TranscodingSettingsController {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
settingsService.setDownsamplingCommand(StringUtils.trim(request.getParameter("downsampleCommand")));
|
|
||||||
settingsService.setHlsCommand(StringUtils.trim(request.getParameter("hlsCommand")));
|
settingsService.setHlsCommand(StringUtils.trim(request.getParameter("hlsCommand")));
|
||||||
settingsService.save();
|
settingsService.save();
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -96,7 +96,7 @@ public class UserSettingsController {
|
||||||
command = (UserSettingsCommand) model.asMap().get("command");
|
command = (UserSettingsCommand) model.asMap().get("command");
|
||||||
}
|
}
|
||||||
command.setUsers(securityService.getAllUsers());
|
command.setUsers(securityService.getAllUsers());
|
||||||
command.setTranscodingSupported(transcodingService.isDownsamplingSupported(null));
|
command.setTranscodingSupported(transcodingService.isTranscodingSupported(null));
|
||||||
command.setTranscodeDirectory(transcodingService.getTranscodeDirectory().getPath());
|
command.setTranscodeDirectory(transcodingService.getTranscodeDirectory().getPath());
|
||||||
command.setTranscodeSchemes(TranscodeScheme.values());
|
command.setTranscodeSchemes(TranscodeScheme.values());
|
||||||
command.setLdapEnabled(settingsService.isLdapEnabled());
|
command.setLdapEnabled(settingsService.isLdapEnabled());
|
||||||
|
|
|
@ -84,7 +84,6 @@ public class SettingsService {
|
||||||
private static final String KEY_PODCAST_EPISODE_DOWNLOAD_COUNT = "PodcastEpisodeDownloadCount";
|
private static final String KEY_PODCAST_EPISODE_DOWNLOAD_COUNT = "PodcastEpisodeDownloadCount";
|
||||||
private static final String KEY_DOWNLOAD_BITRATE_LIMIT = "DownloadBitrateLimit";
|
private static final String KEY_DOWNLOAD_BITRATE_LIMIT = "DownloadBitrateLimit";
|
||||||
private static final String KEY_UPLOAD_BITRATE_LIMIT = "UploadBitrateLimit";
|
private static final String KEY_UPLOAD_BITRATE_LIMIT = "UploadBitrateLimit";
|
||||||
private static final String KEY_DOWNSAMPLING_COMMAND = "DownsamplingCommand4";
|
|
||||||
private static final String KEY_HLS_COMMAND = "HlsCommand3";
|
private static final String KEY_HLS_COMMAND = "HlsCommand3";
|
||||||
private static final String KEY_JUKEBOX_COMMAND = "JukeboxCommand2";
|
private static final String KEY_JUKEBOX_COMMAND = "JukeboxCommand2";
|
||||||
private static final String KEY_VIDEO_IMAGE_COMMAND = "VideoImageCommand";
|
private static final String KEY_VIDEO_IMAGE_COMMAND = "VideoImageCommand";
|
||||||
|
@ -168,7 +167,6 @@ public class SettingsService {
|
||||||
private static final int DEFAULT_PODCAST_EPISODE_DOWNLOAD_COUNT = 1;
|
private static final int DEFAULT_PODCAST_EPISODE_DOWNLOAD_COUNT = 1;
|
||||||
private static final long DEFAULT_DOWNLOAD_BITRATE_LIMIT = 0;
|
private static final long DEFAULT_DOWNLOAD_BITRATE_LIMIT = 0;
|
||||||
private static final long DEFAULT_UPLOAD_BITRATE_LIMIT = 0;
|
private static final long DEFAULT_UPLOAD_BITRATE_LIMIT = 0;
|
||||||
private static final String DEFAULT_DOWNSAMPLING_COMMAND = "ffmpeg -i %s -map 0:0 -b:a %bk -v 0 -f mp3 -";
|
|
||||||
private static final String DEFAULT_HLS_COMMAND = "ffmpeg -ss %o -t %d -i %s -async 1 -b:v %bk -s %wx%h -ar 44100 -ac 2 -v 0 -f mpegts -c:v libx264 -preset superfast -c:a libmp3lame -threads 0 -";
|
private static final String DEFAULT_HLS_COMMAND = "ffmpeg -ss %o -t %d -i %s -async 1 -b:v %bk -s %wx%h -ar 44100 -ac 2 -v 0 -f mpegts -c:v libx264 -preset superfast -c:a libmp3lame -threads 0 -";
|
||||||
private static final String DEFAULT_JUKEBOX_COMMAND = "ffmpeg -ss %o -i %s -map 0:0 -v 0 -ar 44100 -ac 2 -f s16be -";
|
private static final String DEFAULT_JUKEBOX_COMMAND = "ffmpeg -ss %o -i %s -map 0:0 -v 0 -ar 44100 -ac 2 -f s16be -";
|
||||||
private static final String DEFAULT_VIDEO_IMAGE_COMMAND = "ffmpeg -r 1 -ss %o -t 1 -i %s -s %wx%h -v 0 -f mjpeg -";
|
private static final String DEFAULT_VIDEO_IMAGE_COMMAND = "ffmpeg -r 1 -ss %o -t 1 -i %s -s %wx%h -v 0 -f mjpeg -";
|
||||||
|
@ -216,8 +214,8 @@ public class SettingsService {
|
||||||
|
|
||||||
// Array of obsolete keys. Used to clean property file.
|
// Array of obsolete keys. Used to clean property file.
|
||||||
private static final List<String> OBSOLETE_KEYS = Arrays.asList("PortForwardingPublicPort", "PortForwardingLocalPort",
|
private static final List<String> OBSOLETE_KEYS = Arrays.asList("PortForwardingPublicPort", "PortForwardingLocalPort",
|
||||||
"DownsamplingCommand", "DownsamplingCommand2", "DownsamplingCommand3", "AutoCoverBatch", "MusicMask",
|
"DownsamplingCommand", "DownsamplingCommand2", "DownsamplingCommand3", "DownsamplingCommand4",
|
||||||
"VideoMask", "CoverArtMask, HlsCommand", "HlsCommand2", "JukeboxCommand",
|
"AutoCoverBatch", "MusicMask", "VideoMask", "CoverArtMask, HlsCommand", "HlsCommand2", "JukeboxCommand",
|
||||||
"CoverArtFileTypes", "UrlRedirectCustomHost", "CoverArtLimit", "StreamPort",
|
"CoverArtFileTypes", "UrlRedirectCustomHost", "CoverArtLimit", "StreamPort",
|
||||||
"PortForwardingEnabled", "RewriteUrl", "UrlRedirectCustomUrl", "UrlRedirectContextPath",
|
"PortForwardingEnabled", "RewriteUrl", "UrlRedirectCustomUrl", "UrlRedirectContextPath",
|
||||||
"UrlRedirectFrom", "UrlRedirectionEnabled", "UrlRedirectType", "Port", "HttpsPort",
|
"UrlRedirectFrom", "UrlRedirectionEnabled", "UrlRedirectType", "Port", "HttpsPort",
|
||||||
|
@ -638,14 +636,6 @@ public class SettingsService {
|
||||||
setLong(KEY_UPLOAD_BITRATE_LIMIT, limit);
|
setLong(KEY_UPLOAD_BITRATE_LIMIT, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDownsamplingCommand() {
|
|
||||||
return getProperty(KEY_DOWNSAMPLING_COMMAND, DEFAULT_DOWNSAMPLING_COMMAND);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDownsamplingCommand(String command) {
|
|
||||||
setProperty(KEY_DOWNSAMPLING_COMMAND, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getHlsCommand() {
|
public String getHlsCommand() {
|
||||||
return getProperty(KEY_HLS_COMMAND, DEFAULT_HLS_COMMAND);
|
return getProperty(KEY_HLS_COMMAND, DEFAULT_HLS_COMMAND);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides services for transcoding media. Transcoding is the process of
|
* Provides services for transcoding media. Transcoding is the process of
|
||||||
* converting an audio stream to a different format and/or bit rate. The latter is
|
* converting a media file/stream to a different format and/or bit rate. The latter is
|
||||||
* also called downsampling.
|
* also called downsampling.
|
||||||
*
|
*
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
|
@ -81,6 +81,7 @@ public class TranscodingService {
|
||||||
* @return All active transcodings for the player.
|
* @return All active transcodings for the player.
|
||||||
*/
|
*/
|
||||||
public List<Transcoding> getTranscodingsForPlayer(Player player) {
|
public List<Transcoding> getTranscodingsForPlayer(Player player) {
|
||||||
|
// FIXME - This should probably check isTranscodingInstalled()
|
||||||
return transcodingDao.getTranscodingsForPlayer(player.getId());
|
return transcodingDao.getTranscodingsForPlayer(player.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,13 +174,10 @@ public class TranscodingService {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates parameters for a possibly transcoded or downsampled input stream for the given media file and player combination.
|
* Creates parameters for a possibly transcoded input stream for the given media file and player combination.
|
||||||
* <p/>
|
* <p/>
|
||||||
* A transcoding is applied if it is applicable for the format of the given file, and is activated for the
|
* A transcoding is applied if it is applicable for the format of the given file, and is activated for the
|
||||||
* given player.
|
* given player, and either the desired format or bitrate needs changing.
|
||||||
* <p/>
|
|
||||||
* If no transcoding is applicable, the file may still be downsampled, given that the player is configured
|
|
||||||
* with a bit rate limit which is higher than the actual bit rate of the file.
|
|
||||||
* <p/>
|
* <p/>
|
||||||
* Otherwise, a normal input stream to the original file is returned.
|
* Otherwise, a normal input stream to the original file is returned.
|
||||||
*
|
*
|
||||||
|
@ -232,10 +230,6 @@ public class TranscodingService {
|
||||||
if (transcoding != null && ((maxBitRate != 0 && (bitRate == 0 || bitRate > maxBitRate)) ||
|
if (transcoding != null && ((maxBitRate != 0 && (bitRate == 0 || bitRate > maxBitRate)) ||
|
||||||
(preferredTargetFormat != null && ! mediaFile.getFormat().equalsIgnoreCase(preferredTargetFormat)))) {
|
(preferredTargetFormat != null && ! mediaFile.getFormat().equalsIgnoreCase(preferredTargetFormat)))) {
|
||||||
parameters.setTranscoding(transcoding);
|
parameters.setTranscoding(transcoding);
|
||||||
} else if (isDownsamplingSupported(mediaFile)) {
|
|
||||||
if (bitRate > maxBitRate) {
|
|
||||||
parameters.setDownsample(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parameters.setMaxBitRate(maxBitRate == 0 ? null : maxBitRate);
|
parameters.setMaxBitRate(maxBitRate == 0 ? null : maxBitRate);
|
||||||
|
@ -266,10 +260,6 @@ public class TranscodingService {
|
||||||
return createTranscodedInputStream(parameters);
|
return createTranscodedInputStream(parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parameters.downsample) {
|
|
||||||
return createDownsampledInputStream(parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IOException x) {
|
} catch (IOException x) {
|
||||||
LOG.warn("Transcoder failed: {}. Using original: " + parameters.getMediaFile().getFile().getAbsolutePath(), x.toString());
|
LOG.warn("Transcoder failed: {}. Using original: " + parameters.getMediaFile().getFile().getAbsolutePath(), x.toString());
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
|
@ -467,33 +457,27 @@ public class TranscodingService {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a downsampled input stream to the music file.
|
* Returns whether transcoding is supported (i.e. whether ffmpeg is installed or not).
|
||||||
*
|
*
|
||||||
* @param parameters Downsample parameters.
|
* @param mediaFile If not null, returns whether transcoding is supported for this file.
|
||||||
* @throws IOException If an I/O error occurs.
|
* @return Whether transcoding is supported.
|
||||||
*/
|
*/
|
||||||
private InputStream createDownsampledInputStream(Parameters parameters) throws IOException {
|
public boolean isTranscodingSupported(MediaFile mediaFile) {
|
||||||
String command = settingsService.getDownsamplingCommand();
|
List<Transcoding> transcodings = getAllTranscodings();
|
||||||
return createTranscodeInputStream(command, parameters.getMaxBitRate(), parameters.getVideoTranscodingSettings(),
|
for (Transcoding transcoding : transcodings) {
|
||||||
parameters.getMediaFile(), null);
|
if (! isTranscodingInstalled(transcoding)) {
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
/**
|
if (mediaFile == null) {
|
||||||
* Returns whether downsampling is supported (i.e., whether ffmpeg is installed or not.)
|
return true;
|
||||||
*
|
}
|
||||||
* @param mediaFile If not null, returns whether downsampling is supported for this file.
|
for (String sourceFormat : transcoding.getSourceFormatsAsArray()) {
|
||||||
* @return Whether downsampling is supported.
|
if (sourceFormat.equalsIgnoreCase(mediaFile.getFormat())) {
|
||||||
*/
|
return true;
|
||||||
public boolean isDownsamplingSupported(MediaFile mediaFile) {
|
}
|
||||||
if (mediaFile != null) {
|
|
||||||
boolean isMp3 = "mp3".equalsIgnoreCase(mediaFile.getFormat());
|
|
||||||
if (!isMp3) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
String commandLine = settingsService.getDownsamplingCommand();
|
|
||||||
return isTranscodingStepInstalled(commandLine);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isTranscodingInstalled(Transcoding transcoding) {
|
private boolean isTranscodingInstalled(Transcoding transcoding) {
|
||||||
|
@ -518,7 +502,7 @@ public class TranscodingService {
|
||||||
private Long getExpectedLength(Parameters parameters) {
|
private Long getExpectedLength(Parameters parameters) {
|
||||||
MediaFile file = parameters.getMediaFile();
|
MediaFile file = parameters.getMediaFile();
|
||||||
|
|
||||||
if (!parameters.isDownsample() && !parameters.isTranscode()) {
|
if (!parameters.isTranscode()) {
|
||||||
return file.getFileSize();
|
return file.getFileSize();
|
||||||
}
|
}
|
||||||
Integer duration = file.getDurationSeconds();
|
Integer duration = file.getDurationSeconds();
|
||||||
|
@ -543,10 +527,8 @@ public class TranscodingService {
|
||||||
List<String> steps = Arrays.asList();
|
List<String> steps = Arrays.asList();
|
||||||
if (transcoding != null) {
|
if (transcoding != null) {
|
||||||
steps = Arrays.asList(transcoding.getStep3(), transcoding.getStep2(), transcoding.getStep1());
|
steps = Arrays.asList(transcoding.getStep3(), transcoding.getStep2(), transcoding.getStep1());
|
||||||
} else if (parameters.isDownsample()) {
|
|
||||||
steps = Arrays.asList(settingsService.getDownsamplingCommand());
|
|
||||||
} else {
|
} else {
|
||||||
return true; // neither transcoding nor downsampling
|
return true; // not transcoding
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that were able to predict the length
|
// Verify that were able to predict the length
|
||||||
|
@ -609,14 +591,6 @@ public class TranscodingService {
|
||||||
this.maxBitRate = maxBitRate;
|
this.maxBitRate = maxBitRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDownsample() {
|
|
||||||
return downsample;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDownsample(boolean downsample) {
|
|
||||||
this.downsample = downsample;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isTranscode() {
|
public boolean isTranscode() {
|
||||||
return transcoding != null;
|
return transcoding != null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
<databaseChangeLog
|
||||||
|
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
|
||||||
|
<changeSet id="add-mp3-to-transcode" author="eharris">
|
||||||
|
<preConditions onFail="MARK_RAN">
|
||||||
|
<tableExists tableName="transcoding2" />
|
||||||
|
</preConditions>
|
||||||
|
<update tableName="transcoding2">
|
||||||
|
<column name="source_formats" type="${varchar_type}" value="mp3 ogg oga aac m4a flac wav wma aif aiff ape mpc shn" />
|
||||||
|
<where>source_formats = 'ogg oga aac m4a flac wav wma aif aiff ape mpc shn'</where>
|
||||||
|
</update>
|
||||||
|
<rollback>
|
||||||
|
</rollback>
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<databaseChangeLog
|
||||||
|
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
|
||||||
|
<include file="add-mp3-to-transcode.xml" relativeToChangelogFile="true"/>
|
||||||
|
</databaseChangeLog>
|
|
@ -13,5 +13,6 @@
|
||||||
<include file="6.3/changelog.xml" relativeToChangelogFile="true"/>
|
<include file="6.3/changelog.xml" relativeToChangelogFile="true"/>
|
||||||
<include file="6.4/changelog.xml" relativeToChangelogFile="true"/>
|
<include file="6.4/changelog.xml" relativeToChangelogFile="true"/>
|
||||||
<include file="10.2/changelog.xml" relativeToChangelogFile="true"/>
|
<include file="10.2/changelog.xml" relativeToChangelogFile="true"/>
|
||||||
|
<include file="10.3/changelog.xml" relativeToChangelogFile="true"/>
|
||||||
<include file="10.6/changelog.xml" relativeToChangelogFile="true"/>
|
<include file="10.6/changelog.xml" relativeToChangelogFile="true"/>
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
|
|
|
@ -57,15 +57,6 @@
|
||||||
|
|
||||||
|
|
||||||
<table style="white-space:nowrap" class="indent">
|
<table style="white-space:nowrap" class="indent">
|
||||||
<tr>
|
|
||||||
<td style="font-weight: bold;">
|
|
||||||
<fmt:message key="advancedsettings.downsamplecommand"/>
|
|
||||||
<c:import url="helpToolTip.jsp"><c:param name="topic" value="downsamplecommand"/></c:import>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<input class="monospace" type="text" name="downsampleCommand" size="100" value="${model.downsampleCommand}"/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td style="font-weight: bold;">
|
<td style="font-weight: bold;">
|
||||||
<fmt:message key="advancedsettings.hlscommand"/>
|
<fmt:message key="advancedsettings.hlscommand"/>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue