aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Api/HttpHandlers/AudioHandler.cs
blob: c7adc9a58382168fb8adac39d17c3786413a53c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
using System.Collections.Generic;
using System.IO;
using System.Linq;
using MediaBrowser.Model.Entities;

namespace MediaBrowser.Api.HttpHandlers
{
    /// <summary>
    /// Supported output formats are: mp3,flac,ogg,wav,asf,wma,aac
    /// </summary>
    public class AudioHandler : BaseMediaHandler<Audio>
    {
        /// <summary>
        /// Overriding to provide mp3 as a default, since pretty much every device supports it
        /// </summary>
        protected override IEnumerable<string> OutputFormats
        {
            get
            {
                IEnumerable<string> vals = base.OutputFormats;

                return vals.Any() ? vals : new string[] { "mp3" };
            }
        }

        /// <summary>
        /// We can output these files directly, but we can't encode them
        /// </summary>
        protected override IEnumerable<string> UnsupportedOutputEncodingFormats
        {
            get
            {
                return new string[] { "wma", "aac" };
            }
        }

        public IEnumerable<int> AudioBitRates
        {
            get
            {
                string val = QueryString["audiobitrates"];

                if (string.IsNullOrEmpty(val))
                {
                    return new int[] { };
                }

                return val.Split(',').Select(v => int.Parse(v));
            }
        }

        private int? GetMaxAcceptedBitRate(string audioFormat)
        {
            if (!AudioBitRates.Any())
            {
                return null;
            }

            int index = OutputFormats.ToList().IndexOf(audioFormat);

            return AudioBitRates.ElementAt(index);
        }

        /// <summary>
        /// Determines whether or not the original file requires transcoding
        /// </summary>
        protected override bool RequiresConversion()
        {
            if (base.RequiresConversion())
            {
                return true;
            }

            string currentFormat = Path.GetExtension(LibraryItem.Path).Replace(".", string.Empty);
            
            int? bitrate = GetMaxAcceptedBitRate(currentFormat);

            // If the bitrate is greater than our desired bitrate, we need to transcode
            if (bitrate.HasValue && bitrate.Value < LibraryItem.BitRate)
            {
                return true;
            }

            // If the number of channels is greater than our desired channels, we need to transcode
            if (AudioChannels.HasValue && AudioChannels.Value < LibraryItem.Channels)
            {
                return true;
            }

            // If the sample rate is greater than our desired sample rate, we need to transcode
            if (AudioSampleRate.HasValue && AudioSampleRate.Value < LibraryItem.SampleRate)
            {
                return true;
            }

            // Yay
            return false;
        }

        /// <summary>
        /// Creates arguments to pass to ffmpeg
        /// </summary>
        protected override string GetCommandLineArguments()
        {
            List<string> audioTranscodeParams = new List<string>();

            string outputFormat = GetConversionOutputFormat();

            int? bitrate = GetMaxAcceptedBitRate(outputFormat);

            if (bitrate.HasValue)
            {
                audioTranscodeParams.Add("-ab " + bitrate.Value);
            }

            int? channels = GetNumAudioChannelsParam();

            if (channels.HasValue)
            {
                audioTranscodeParams.Add("-ac " + channels.Value);
            }

            int? sampleRate = GetSampleRateParam();

            if (sampleRate.HasValue)
            {
                audioTranscodeParams.Add("-ar " + sampleRate.Value);
            }

            audioTranscodeParams.Add("-f " + outputFormat);

            return "-i \"" + LibraryItem.Path + "\" -vn " + string.Join(" ", audioTranscodeParams.ToArray()) + " -";
        }

        /// <summary>
        /// Gets the number of audio channels to specify on the command line
        /// </summary>
        private int? GetNumAudioChannelsParam()
        {
            // If the user requested a max number of channels
            if (AudioChannels.HasValue)
            {
                // Only specify the param if we're going to downmix
                if (AudioChannels.Value < LibraryItem.Channels)
                {
                    return AudioChannels.Value;
                }
            }

            return null;
        }

        /// <summary>
        /// Gets the number of audio channels to specify on the command line
        /// </summary>
        private int? GetSampleRateParam()
        {
            // If the user requested a max value
            if (AudioSampleRate.HasValue)
            {
                // Only specify the param if we're going to downmix
                if (AudioSampleRate.Value < LibraryItem.SampleRate)
                {
                    return AudioSampleRate.Value;
                }
            }

            return null;
        }
    }
}