Merge remote-tracking branch 'origin/pr/1035'

master
Andrew DeMaria 6 years ago
commit 72e4c7b965
No known key found for this signature in database
GPG Key ID: 0A3F5E91F8364EDF
  1. 6
      airsonic-main/pom.xml
  2. 165
      airsonic-main/src/main/java/org/airsonic/player/controller/StreamController.java
  3. 2
      airsonic-main/src/main/java/org/airsonic/player/controller/TranscodingSettingsController.java
  4. 3
      airsonic-main/src/main/java/org/airsonic/player/io/RangeOutputStream.java
  5. 9
      airsonic-main/src/main/java/org/airsonic/player/service/SettingsService.java
  6. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_bg.properties
  7. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_ca.properties
  8. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_cs.properties
  9. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_da.properties
  10. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_de.properties
  11. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_el.properties
  12. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_en.properties
  13. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_en_GB.properties
  14. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_es.properties
  15. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_et.properties
  16. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_fi.properties
  17. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_fr.properties
  18. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_is.properties
  19. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_it.properties
  20. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_ja_JP.properties
  21. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_ko.properties
  22. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_mk.properties
  23. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_nl.properties
  24. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_nn.properties
  25. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_no.properties
  26. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_pl.properties
  27. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_pt.properties
  28. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_pt_BR.properties
  29. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_pt_PT.properties
  30. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_ru.properties
  31. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_sl.properties
  32. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_sv.properties
  33. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_uk.properties
  34. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_zh_CN.properties
  35. 1
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_zh_TW.properties
  36. 5
      airsonic-main/src/main/webapp/WEB-INF/jsp/transcodingSettings.jsp

@ -184,6 +184,12 @@
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>

@ -41,6 +41,7 @@ import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -52,14 +53,13 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A controller which streams the content of a {@link PlayQueue} to a remote
* {@link Player}.
* A controller which streams the content of a {@link PlayQueue} to a remote {@link Player}.
*
* @author Sindre Mehus
*/
@Controller
@RequestMapping(value = {"/stream/**", "/ext/stream/**"})
public class StreamController {
public class StreamController {
private static final Logger LOG = LoggerFactory.getLogger(StreamController.class);
@ -94,7 +94,8 @@ public class StreamController {
try {
if (!(authentication instanceof JWTAuthenticationToken) && !user.isStreamRole()) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Streaming is forbidden for user " + user.getUsername());
response.sendError(HttpServletResponse.SC_FORBIDDEN,
"Streaming is forbidden for user " + user.getUsername());
return;
}
@ -132,9 +133,10 @@ public class StreamController {
if (isSingleFile) {
if (!(authentication instanceof JWTAuthenticationToken) && !securityService.isFolderAccessAllowed(file, user.getUsername())) {
if (!(authentication instanceof JWTAuthenticationToken) && !securityService.isFolderAccessAllowed(file,
user.getUsername())) {
response.sendError(HttpServletResponse.SC_FORBIDDEN,
"Access to file " + file.getId() + " is forbidden for user " + user.getUsername());
"Access to file " + file.getId() + " is forbidden for user " + user.getUsername());
return;
}
@ -151,28 +153,48 @@ public class StreamController {
playQueue.addFiles(true, file);
player.setPlayQueue(playQueue);
if (settingsService.isEnableSeek() && !file.isVideo()) {
response.setIntHeader("ETag", file.getId());
response.setHeader("Accept-Ranges", "bytes");
}
TranscodingService.Parameters parameters = transcodingService.getParameters(file, player, maxBitRate, preferredTargetFormat, null);
long fileLength = getFileLength(parameters);
TranscodingService.Parameters parameters = transcodingService.getParameters(file, player, maxBitRate,
preferredTargetFormat, null);
boolean isConversion = parameters.isDownsample() || parameters.isTranscode();
boolean estimateContentLength = ServletRequestUtils.getBooleanParameter(request, "estimateContentLength", false);
boolean estimateContentLength = ServletRequestUtils.getBooleanParameter(request,
"estimateContentLength", false);
boolean isHls = ServletRequestUtils.getBooleanParameter(request, "hls", false);
range = getRange(request, file);
if (settingsService.isEnableSeek() && range != null && !file.isVideo()) {
LOG.info("{}: Got HTTP range: {}", request.getRemoteAddr(), range);
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
Util.setContentLength(response, range.isClosed() ? range.size() : fileLength - range.getFirstBytePos());
long lastBytePos = range.getLastBytePos() != null ? range.getLastBytePos() : fileLength - 1;
response.setHeader("Content-Range", "bytes " + range.getFirstBytePos() + "-" + lastBytePos + "/" + fileLength);
} else if (!isHls && (!isConversion || estimateContentLength)) {
Util.setContentLength(response, fileLength);
// Wrangle response length and ranges.
//
// Support ranges as long as we're not transcoding; video is always assumed to transcode
if (isConversion || file.isVideo()) {
// Use chunked transfer; do not accept range requests
response.setStatus(HttpServletResponse.SC_OK);
response.setHeader("Accept-Ranges", "none");
} else {
// Not transcoding, partial content permitted because we know the final size
long contentLength;
// If range was requested, respond in kind
range = getRange(request, file);
if (range != null) {
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
response.setHeader("Accept-Ranges", "bytes");
// Both ends are inclusive
long startByte = range.getFirstBytePos();
long endByte = range.isClosed() ? range.getLastBytePos() : file.getFileSize() - 1;
response.setHeader("Content-Range",
String.format("bytes %d-%d/%d", startByte, endByte, file.getFileSize()));
contentLength = endByte + 1 - startByte;
} else {
// No range was requested, give back the whole file
response.setStatus(HttpServletResponse.SC_OK);
contentLength = file.getFileSize();
}
response.setIntHeader("ETag", file.getId());
Util.setContentLength(response, contentLength);
}
// Set content type of response
if (isHls) {
response.setContentType(StringUtil.getMimeType("ts")); // HLS is always MPEG TS.
} else {
@ -187,6 +209,7 @@ public class StreamController {
}
}
// All headers are set, stop if that's all the client requested.
if (request.getMethod().equals("HEAD")) {
return;
}
@ -202,49 +225,32 @@ public class StreamController {
status = statusService.createStreamStatus(player);
in = new PlayQueueInputStream(player, status, maxBitRate, preferredTargetFormat, videoTranscodingSettings, transcodingService,
audioScrobblerService, mediaFileService, searchService);
OutputStream out = RangeOutputStream.wrap(response.getOutputStream(), range);
// Enabled SHOUTcast, if requested.
boolean isShoutCastRequested = "1".equals(request.getHeader("icy-metadata"));
if (isShoutCastRequested && !isSingleFile) {
response.setHeader("icy-metaint", "" + ShoutCastOutputStream.META_DATA_INTERVAL);
response.setHeader("icy-notice1", "This stream is served using Airsonic");
response.setHeader("icy-notice2", "Airsonic - Free media streamer");
response.setHeader("icy-name", "Airsonic");
response.setHeader("icy-genre", "Mixed");
response.setHeader("icy-url", "https://airsonic.github.io/");
out = new ShoutCastOutputStream(out, player.getPlayQueue(), settingsService);
}
final int BUFFER_SIZE = 2048;
byte[] buf = new byte[BUFFER_SIZE];
in = new PlayQueueInputStream(player, status, maxBitRate, preferredTargetFormat, videoTranscodingSettings,
transcodingService, audioScrobblerService, mediaFileService, searchService);
while (true) {
try (OutputStream out = makeOutputStream(request, response, range, isSingleFile, player, settingsService)) {
final int BUFFER_SIZE = 2048;
byte[] buf = new byte[BUFFER_SIZE];
// Check if stream has been terminated.
if (status.terminated()) {
return;
}
if (player.getPlayQueue().getStatus() == PlayQueue.Status.STOPPED) {
if (isPodcast || isSingleFile) {
break;
} else {
sendDummy(buf, out);
}
} else {
int n = in.read(buf);
if (n == -1) {
while (!status.terminated()) {
if (player.getPlayQueue().getStatus() == PlayQueue.Status.STOPPED) {
if (isPodcast || isSingleFile) {
break;
} else {
sendDummy(buf, out);
}
} else {
out.write(buf, 0, n);
int n = in.read(buf);
if (n == -1) {
if (isPodcast || isSingleFile) {
break;
} else {
sendDummy(buf, out);
}
} else {
out.write(buf, 0, n);
}
}
}
}
@ -257,7 +263,10 @@ public class StreamController {
shouldCatch |= Util.isInstanceOfClassName(e, "org.apache.catalina.connector.ClientAbortException");
shouldCatch |= Util.isInstanceOfClassName(e, "org.eclipse.jetty.io.EofException");
if (shouldCatch) {
LOG.info("{}: Client unexpectedly closed connection while loading {} ({})", request.getRemoteAddr(), Util.getAnonymizedURLForRequest(request), e.getCause().toString());
LOG.info("{}: Client unexpectedly closed connection while loading {} ({})",
request.getRemoteAddr(),
Util.getAnonymizedURLForRequest(request),
e.getCause().toString());
return;
}
@ -274,6 +283,31 @@ public class StreamController {
return;
}
/**
* Construct an appropriate output stream based on the request.
* <p>
* This is responsible for limiting the output to the given range (if not null) and injecting Shoutcast metadata
* into the stream if requested.
*/
private OutputStream makeOutputStream(HttpServletRequest request, HttpServletResponse response, HttpRange range,
boolean isSingleFile, Player player, SettingsService settingsService)
throws IOException {
OutputStream out = RangeOutputStream.wrap(response.getOutputStream(), range);
// Enabled SHOUTcast, if requested.
boolean isShoutCastRequested = "1".equals(request.getHeader("icy-metadata"));
if (isShoutCastRequested && !isSingleFile) {
response.setHeader("icy-metaint", "" + ShoutCastOutputStream.META_DATA_INTERVAL);
response.setHeader("icy-notice1", "This stream is served using Airsonic");
response.setHeader("icy-notice2", "Airsonic - Free media streamer");
response.setHeader("icy-name", "Airsonic");
response.setHeader("icy-genre", "Mixed");
response.setHeader("icy-url", "https://airsonic.github.io/");
out = new ShoutCastOutputStream(out, player.getPlayQueue(), settingsService);
}
return out;
}
private void setContentDuration(HttpServletResponse response, MediaFile file) {
if (file.getDurationSeconds() != null) {
response.setHeader("X-Content-Duration", String.format("%.1f", file.getDurationSeconds().doubleValue()));
@ -314,6 +348,7 @@ public class StreamController {
return duration * (long)maxBitRate * 1000L / 8L;
}
@Nullable
private HttpRange getRange(HttpServletRequest request, MediaFile file) {
// First, look for "Range" HTTP header.
@ -325,13 +360,11 @@ public class StreamController {
// Second, look for "offsetSeconds" request parameter.
String offsetSeconds = request.getParameter("offsetSeconds");
range = parseAndConvertOffsetSeconds(offsetSeconds, file);
if (range != null) {
return range;
}
return range;
return null;
}
@Nullable
private HttpRange parseAndConvertOffsetSeconds(String offsetSeconds, MediaFile file) {
if (offsetSeconds == null) {
return null;
@ -355,12 +388,14 @@ public class StreamController {
}
}
private VideoTranscodingSettings createVideoTranscodingSettings(MediaFile file, HttpServletRequest request) throws ServletRequestBindingException {
private VideoTranscodingSettings createVideoTranscodingSettings(MediaFile file, HttpServletRequest request)
throws ServletRequestBindingException {
Integer existingWidth = file.getWidth();
Integer existingHeight = file.getHeight();
Integer maxBitRate = ServletRequestUtils.getIntParameter(request, "maxBitRate");
int timeOffset = ServletRequestUtils.getIntParameter(request, "timeOffset", 0);
int defaultDuration = file.getDurationSeconds() == null ? Integer.MAX_VALUE : file.getDurationSeconds() - timeOffset;
int defaultDuration = file.getDurationSeconds() == null ? Integer.MAX_VALUE :
file.getDurationSeconds() - timeOffset;
int duration = ServletRequestUtils.getIntParameter(request, "duration", defaultDuration);
boolean hls = ServletRequestUtils.getBooleanParameter(request, "hls", false);

@ -56,7 +56,6 @@ public class TranscodingSettingsController {
map.put("transcodings", transcodingService.getAllTranscodings());
map.put("transcodeDirectory", transcodingService.getTranscodeDirectory());
map.put("enableSeek", settingsService.isEnableSeek());
map.put("downsampleCommand", settingsService.getDownsamplingCommand());
map.put("hlsCommand", settingsService.getHlsCommand());
map.put("brand", settingsService.getBrand());
@ -132,7 +131,6 @@ public class TranscodingSettingsController {
return error;
}
}
settingsService.setEnableSeek(request.getParameter("enableSeek") != null);
settingsService.setDownsamplingCommand(StringUtils.trim(request.getParameter("downsampleCommand")));
settingsService.setHlsCommand(StringUtils.trim(request.getParameter("hlsCommand")));
settingsService.save();

@ -55,7 +55,8 @@ public class RangeOutputStream extends FilterOutputStream {
* @return The possibly wrapped output stream.
*/
public static OutputStream wrap(OutputStream out, HttpRange range) {
if (range == null) {
// Skip filtering if there's no range or it represents the entire stream.
if (range == null || (range.getFirstBytePos() == 0 && !range.isClosed())) {
return out;
}
return new RangeOutputStream(out, range);

@ -83,7 +83,6 @@ public class SettingsService {
private static final String KEY_PODCAST_EPISODE_DOWNLOAD_COUNT = "PodcastEpisodeDownloadCount";
private static final String KEY_DOWNLOAD_BITRATE_LIMIT = "DownloadBitrateLimit";
private static final String KEY_UPLOAD_BITRATE_LIMIT = "UploadBitrateLimit";
private static final String KEY_ENABLE_SEEK = "EnableSeek1";
private static final String KEY_DOWNSAMPLING_COMMAND = "DownsamplingCommand4";
private static final String KEY_HLS_COMMAND = "HlsCommand3";
private static final String KEY_JUKEBOX_COMMAND = "JukeboxCommand2";
@ -624,14 +623,6 @@ public class SettingsService {
setLong(KEY_UPLOAD_BITRATE_LIMIT, limit);
}
public boolean isEnableSeek() {
return getBoolean(KEY_ENABLE_SEEK, DEFAULT_ENABLE_SEEK);
}
public void setEnableSeek(boolean enableSeek) {
setBoolean(KEY_ENABLE_SEEK, enableSeek);
}
public String getDownsamplingCommand() {
return getProperty(KEY_DOWNSAMPLING_COMMAND, DEFAULT_DOWNSAMPLING_COMMAND);
}

@ -413,7 +413,6 @@ transcodingsettings.step2=\u0421\u0442\u044A\u043F\u043A\u0430 2
transcodingsettings.step3=\u0421\u0442\u044A\u043F\u043A\u0430 3
transcodingsettings.add=\u0414\u043E\u0431\u0430\u0432\u0438 \u043A\u043E\u043D\u0432\u0435\u0440\u0442\u0438\u0440\u0430\u043D\u0435
transcodingsettings.defaultactive=\u041F\u043E \u043F\u043E\u0434\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043D\u0435
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=\u041F\u0440\u0435\u043F\u043E\u0440\u044A\u0447\u0438\u0442\u0435\u043B\u043D\u0430 \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044F
transcodingsettings.noname=\u041C\u043E\u043B\u044F \u043F\u043E\u0441\u043E\u0447\u0435\u0442\u0435 \u0438\u043C\u0435.
transcodingsettings.nosourceformat=\u041C\u043E\u043B\u044F \u043F\u043E\u0441\u043E\u0447\u0435\u0442\u0435 \u0444\u043E\u0440\u043C\u0430\u0442\u0430 \u043E\u0442 \u043A\u043E\u0439\u0442\u043E \u0449\u0435 \u0441\u0435 \u043A\u043E\u043D\u0432\u0435\u0440\u0442\u0438\u0440\u0430.

@ -413,7 +413,6 @@ transcodingsettings.step2=Pas 2
transcodingsettings.step3=Pas 3
transcodingsettings.add=Add transcoding
transcodingsettings.defaultactive=Enable transcoding settings for all existing and new players.
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Recommended configuration
transcodingsettings.noname=Si us plau, especifiqui un nom.
transcodingsettings.nosourceformat=Si us plau, especifiqui un format des d'on convertir.

@ -413,7 +413,6 @@ transcodingsettings.step2=Krok 2
transcodingsettings.step3=Krok 3
transcodingsettings.add=P\u0159idat p\u0159ek\u00F3dov\u00E1n\u00ED
transcodingsettings.defaultactive=Povolit toto p\u0159ek\u00F3dov\u00E1n\u00ED pro v\u0161echny existuj\u00EDc\u00ED a nov\u00E9 p\u0159ehr\u00E1va\u010De.
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Doporu\u010Den\u00E1 konfigurace
transcodingsettings.noname=Zadejte n\u00E1zev.
transcodingsettings.nosourceformat=Zadejte form\u00E1t, ze kter\u00E9ho p\u0159ev\u00E1d\u011Bt

@ -413,7 +413,6 @@ transcodingsettings.step2=Trin 2
transcodingsettings.step3=Trin 3
transcodingsettings.add=Tilf\u00F8j kodning
transcodingsettings.defaultactive=Standard
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Recommended configuration
transcodingsettings.noname=Angiv et navn.
transcodingsettings.nosourceformat=Angiv formatet til at konvertere fra.

@ -413,7 +413,6 @@ transcodingsettings.step2=Schritt 2
transcodingsettings.step3=Schritt 3
transcodingsettings.add=Transcoding hinzuf\u00FCgen
transcodingsettings.defaultactive=Standard
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Empfohlene Konfiguratiom
transcodingsettings.noname=Bitte einen Namen eingeben.
transcodingsettings.nosourceformat=Bitte das Format angeben von dem konvertiert wird.

@ -413,7 +413,6 @@ transcodingsettings.step2=\u0392\u03AE\u03BC\u03B1 2
transcodingsettings.step3=\u0392\u03AE\u03BC\u03B1 3
transcodingsettings.add=\u03A0\u03C1\u03CC\u03C3\u03B8\u03B5\u03C3\u03B7 \u03B5\u03C0\u03B1\u03BD\u03B1\u03BA\u03C9\u03B4\u03B9\u03BA\u03BF\u03C0\u03BF\u03AF\u03B7\u03C3\u03B7\u03C2
transcodingsettings.defaultactive=\u03A0\u03C1\u03BF\u03B5\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=\u03A0\u03C1\u03BF\u03C4\u03B5\u03B9\u03BD\u03CC\u03BC\u03B5\u03BD\u03B7 \u03B4\u03B9\u03B1\u03BC\u03CC\u03C1\u03C6\u03C9\u03C3\u03B7
transcodingsettings.noname=\u03A0\u03C1\u03BF\u03C3\u03B4\u03B9\u03BF\u03C1\u03AF\u03C3\u03C4\u03B5 \u03AD\u03BD\u03B1 \u03CC\u03BD\u03BF\u03BC\u03B1
transcodingsettings.nosourceformat=\u03A0\u03B1\u03C1\u03B1\u03BA\u03B1\u03BB\u03CE \u03C0\u03C1\u03BF\u03C3\u03B4\u03B9\u03BF\u03C1\u03AF\u03C3\u03C4\u03B5 \u03C4\u03BF\u03BD \u03C4\u03CD\u03C0\u03BF \u03BC\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE\u03C2 \u03B1\u03C0\u03CC.

@ -413,7 +413,6 @@ transcodingsettings.step2=Step 2
transcodingsettings.step3=Step 3
transcodingsettings.add=Add transcoding
transcodingsettings.defaultactive=Enable transcoding settings for all existing and new players.
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Recommended configuration
transcodingsettings.noname=Please specify a name.
transcodingsettings.nosourceformat=Please specify the format to convert from.

@ -413,7 +413,6 @@ transcodingsettings.step2=Step 2
transcodingsettings.step3=Step 3
transcodingsettings.add=Add transcoding
transcodingsettings.defaultactive=Enable transcoding settings for all existing and new players.
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Recommended configuration
transcodingsettings.noname=Please specify a name.
transcodingsettings.nosourceformat=Please specify the format to convert from.

@ -413,7 +413,6 @@ transcodingsettings.step2=Paso 2
transcodingsettings.step3=Paso 3
transcodingsettings.add=A\u00F1adir transcodificaci\u00F3n
transcodingsettings.defaultactive=Habilitar esta transcodificaci\u00F3n para todos las reproducciones nuevas y existentes.
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Configuraci\u00F3n recomendada
transcodingsettings.noname=Por favor especifique un nombre.
transcodingsettings.nosourceformat=Por favor especifique un formato desde el que convertir.

@ -413,7 +413,6 @@ transcodingsettings.step2=2. samm
transcodingsettings.step3=3. samm
transcodingsettings.add=Lisa konverditav
transcodingsettings.defaultactive=Luba see konvertimine kõikidel olemasolevatel ja uutele meediaesitajatel.
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Soovitatavad seadistused
transcodingsettings.noname=Täpsusta nimi.
transcodingsettings.nosourceformat=Täpsusta, mis formaadist konverditakse.

@ -413,7 +413,6 @@ transcodingsettings.step2=Vaihe 2
transcodingsettings.step3=Vaihe 3
transcodingsettings.add=Lis\u00E4\u00E4 uusi s\u00E4\u00E4nt\u00F6
transcodingsettings.defaultactive=Oletus
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Recommended configuration
transcodingsettings.noname=Anna s\u00E4\u00E4nn\u00F6lle nimi.
transcodingsettings.nosourceformat=M\u00E4\u00E4rit\u00E4 mist\u00E4 tiedostomuodosta muunnetaan.

@ -413,7 +413,6 @@ transcodingsettings.step2=Etape 2
transcodingsettings.step3=Etape 3
transcodingsettings.add=Ajouter un transcodage
transcodingsettings.defaultactive=Par d\u00E9faut
transcodingsettings.enableseek=Activer la recherche sur les transcodes (peut ne pas fonctionner correctement avec les codecs VBR)
transcodingsettings.recommended=Configuration recommand\u00E9e
transcodingsettings.noname=Veuillez indiquer un nom.
transcodingsettings.nosourceformat=Veuillez indiquer le format de la source.

@ -413,7 +413,6 @@ transcodingsettings.step2=Skref 2
transcodingsettings.step3=Skref 3
transcodingsettings.add=B\u00E6ta VI\u00F0 transcoding
transcodingsettings.defaultactive=Venjulegt
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Recommended configuration
transcodingsettings.noname=Vinsamlegast Sl\u00E1\u00F0u inn Nafn.
transcodingsettings.nosourceformat=Vinsamlegast veldu til a\u00F0 breyta Fr\u00E1.

@ -413,7 +413,6 @@ transcodingsettings.step2=Passo 2
transcodingsettings.step3=Passo 3
transcodingsettings.add=Aggiungi transcodifica
transcodingsettings.defaultactive=Predefinito
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Configurazione consigliata
transcodingsettings.noname=Per favore specifica un nome.
transcodingsettings.nosourceformat=Per favore specifica il formato dal quale convertire.

@ -413,7 +413,6 @@ transcodingsettings.step2=\u7B2C2\u6BB5\u968E
transcodingsettings.step3=\u7B2C3\u6BB5\u968E
transcodingsettings.add=\u30C8\u30E9\u30F3\u30B9\u30B3\u30FC\u30C7\u30A3\u30F3\u30B0\u8A2D\u5B9A\u3092\u8FFD\u52A0
transcodingsettings.defaultactive=\u30C7\u30D5\u30A9\u30EB\u30C8
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=\u63A8\u5968\u3055\u308C\u308B\u8A2D\u5B9A
transcodingsettings.noname=\u540D\u524D\u304C\u3042\u308A\u307E\u305B\u3093\u3002
transcodingsettings.nosourceformat=\u5909\u63DB\u5143\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002

@ -413,7 +413,6 @@ transcodingsettings.step2=2 \uB2E8\uACC4
transcodingsettings.step3=3 \uB2E8\uACC4
transcodingsettings.add=\uD30C\uC77C \uBCC0\uD658 \uCD94\uAC00
transcodingsettings.defaultactive=\uAE30\uBCF8\uAC12
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=\uCD94\uCC9C\uD558\uB294 \uBCC0\uD658 \uBC29\uBC95
transcodingsettings.noname=\uBCC0\uD658 \uC774\uB984\uC744 \uB2E4\uC2DC \uC9C0\uC815\uD574\uC8FC\uC138\uC694.
transcodingsettings.nosourceformat=\uC6D0\uBCF8 \uD30C\uC77C \uD0C0\uC785\uC744 \uB2E4\uC2DC \uC9C0\uC815\uD574\uC8FC\uC138\uC694.

@ -413,7 +413,6 @@ transcodingsettings.step2=Step 2
transcodingsettings.step3=Step 3
transcodingsettings.add=Add transcoding
transcodingsettings.defaultactive=Enable transcoding settings for all existing and new players.
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Recommended configuration
transcodingsettings.noname=Please specify a name.
transcodingsettings.nosourceformat=Please specify the format to convert from.

@ -413,7 +413,6 @@ transcodingsettings.step2=Stap 2
transcodingsettings.step3=Stap 3
transcodingsettings.add=Voeg conversie toe
transcodingsettings.defaultactive=Activeer deze conversie voor alle bestaande en nieuwe afspelers.
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Aanbevolen configuratie
transcodingsettings.noname=Geef een naam op.
transcodingsettings.nosourceformat=Specificeer het te converteren formaat.

@ -413,7 +413,6 @@ transcodingsettings.step2=Steg 2
transcodingsettings.step3=Steg 3
transcodingsettings.add=Legg til transkoding
transcodingsettings.defaultactive=Standard
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Recommended configuration
transcodingsettings.noname=Ver venleg og skriv eit namn.
transcodingsettings.nosourceformat=Skriv formatet det skal konverterast fr\u00E5.

@ -413,7 +413,6 @@ transcodingsettings.step2=Steg 2
transcodingsettings.step3=Steg 3
transcodingsettings.add=Legg til transkoding
transcodingsettings.defaultactive=Standard
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Recommended configuration
transcodingsettings.noname=Vennligst angi et navn.
transcodingsettings.nosourceformat=Angi formatet det skal konverteres fra.

@ -413,7 +413,6 @@ transcodingsettings.step2=Krok 2
transcodingsettings.step3=Krok 3
transcodingsettings.add=Dodaj transkodowanie
transcodingsettings.defaultactive=Standadrowe
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Zalecana konfiguracja
transcodingsettings.noname=Prosz\u0119 okre\u015Bli\u0107 nazw\u0119
transcodingsettings.nosourceformat=Prosz\u0119 okre\u015Bli\u0107 format \u017Ar\u00F3d\u0142owy

@ -413,7 +413,6 @@ transcodingsettings.step2=Passo 2
transcodingsettings.step3=Passo 3
transcodingsettings.add=Adicionar transcodifica\u00E7\u00E3o
transcodingsettings.defaultactive=Padr\u00E3o
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Recommended configuration
transcodingsettings.noname=Por favor especifique o nome.
transcodingsettings.nosourceformat=Por favor, especifique o formato para converter de.

@ -413,7 +413,6 @@ transcodingsettings.step2=Step 2
transcodingsettings.step3=Step 3
transcodingsettings.add=Add transcoding
transcodingsettings.defaultactive=Enable transcoding settings for all existing and new players.
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Recommended configuration
transcodingsettings.noname=Please specify a name.
transcodingsettings.nosourceformat=Please specify the format to convert from.

@ -413,7 +413,6 @@ transcodingsettings.step2=Step 2
transcodingsettings.step3=Step 3
transcodingsettings.add=Add transcoding
transcodingsettings.defaultactive=Enable transcoding settings for all existing and new players.
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Recommended configuration
transcodingsettings.noname=Please specify a name.
transcodingsettings.nosourceformat=Please specify the format to convert from.

@ -413,7 +413,6 @@ transcodingsettings.step2=\u0428\u0430\u0433 2
transcodingsettings.step3=\u0428\u0430\u0433 3
transcodingsettings.add=\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u043A\u043E\u043D\u0432\u0435\u0440\u0442\u043E\u0440
transcodingsettings.defaultactive=\u041F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Recommended configuration
transcodingsettings.noname=\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u0438\u043C\u044F.
transcodingsettings.nosourceformat=\u0443\u043A\u0430\u0436\u0438\u0442\u0435 \u043A\u043E\u043D\u0432\u0435\u0440\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0441.

@ -413,7 +413,6 @@ transcodingsettings.step2=2. korak
transcodingsettings.step3=3. korak
transcodingsettings.add=Dodaj prekodiranje
transcodingsettings.defaultactive=Privzeto
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Priporo\u010Dene nastavitve
transcodingsettings.noname=Prosimo, dolo\u010Dite ime.
transcodingsettings.nosourceformat=Prosimo, dolo\u010Dite obliko zapisa vhodne datoteke.

@ -413,7 +413,6 @@ transcodingsettings.step2=Steg 2
transcodingsettings.step3=Steg 3
transcodingsettings.add=L\u00E4gg till transcoding
transcodingsettings.defaultactive=Standard
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Rekommenderad konfiguration
transcodingsettings.noname=V\u00E4nligen ange ett namn.
transcodingsettings.nosourceformat=V\u00E4nligen ange ett format att konvertera fr\u00E5n.

@ -413,7 +413,6 @@ transcodingsettings.step2=Step 2
transcodingsettings.step3=Step 3
transcodingsettings.add=Add transcoding
transcodingsettings.defaultactive=Enable transcoding settings for all existing and new players.
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=Рекомендована конфігурація
transcodingsettings.noname=Please specify a name.
transcodingsettings.nosourceformat=Please specify the format to convert from.

@ -413,7 +413,6 @@ transcodingsettings.step2=\u6B65\u9AA4\u4E8C
transcodingsettings.step3=\u6B65\u9AA4\u4E09
transcodingsettings.add=\u6DFB\u52A0
transcodingsettings.defaultactive=\u4E3A\u73B0\u6709\u548C\u65B0\u64AD\u653E\u5668\u542F\u7528\u8FD9\u9879\u8F6C\u7801\u8BBE\u7F6E
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=\u63A8\u8350\u8BBE\u7F6E
transcodingsettings.noname=\u8BF7\u6307\u5B9A\u4E00\u4E2A\u540D\u79F0.
transcodingsettings.nosourceformat=\u8BF7\u6307\u5B9A\u8F6C\u6362\u683C\u5F0F.

@ -413,7 +413,6 @@ transcodingsettings.step2=\u6B65\u9A5F\u4E8C
transcodingsettings.step3=\u6B65\u9A5F\u4E09
transcodingsettings.add=\u65B0\u589E\u8F49\u78BC\u5668
transcodingsettings.defaultactive=\u9810\u8A2D
transcodingsettings.enableseek=Enable seeking on transcodes (might not work well with VBR codecs)
transcodingsettings.recommended=\u5EFA\u8B70\u7684\u8A2D\u5B9A
transcodingsettings.noname=\u8ACB\u6307\u5B9A\u4E00\u500B\u540D\u7A31\u3002
transcodingsettings.nosourceformat=\u8ACB\u6307\u5B9A\u8F49\u63DB\u7684\u4F86\u6E90\u683C\u5F0F\u3002

@ -59,11 +59,6 @@
<table style="white-space:nowrap" class="indent">
<tr>
<td>
<input type="checkbox" id="enableSeek" name="enableSeek" ${model.enableSeek ? "checked" : ""}/>
<label for="enableSeek"><fmt:message key="transcodingsettings.enableseek"/></label>
</td>
<tr>
<td style="font-weight: bold;">
<fmt:message key="advancedsettings.downsamplecommand"/>

Loading…
Cancel
Save