private long getVideoBitrateBasedOnFileBitrate() {
    // file bitrate
    String fileBitrate = conversionSetting.getFfProbe().getFormat().getBit_rate();
    long fbr;
    if (fileBitrate == null || fileBitrate.trim().length() == 0) {
      return 0l;
    } else {
      try {
        fbr = Long.parseLong(fileBitrate);
      } catch (Exception e) {
        // number format exception
        return 0l;
      }
    }

    // audio bitrate
    long abr;
    Stream audioStream = getStream(CODEC_TYPE_AUDIO);
    String audioBitrate = audioStream.getBit_rate();
    try {
      abr = Long.parseLong(audioBitrate);
    } catch (Exception e) {
      // number format exception
      abr = Settings.getDefaultPerChannelAudioBitRate() * audioStream.getChannels();
    }

    return fbr - abr;
  }
 private long getVideoBitrateBasedOnVideoStreamBitRate() {
   Stream videoStream = getStream(CODEC_TYPE_VIDEO);
   try {
     return Long.parseLong(videoStream.getBit_rate());
   } catch (Exception e) {
     // number format exception
     return 0l;
   }
 }
 private int internalGetNumberOfSubtitles() {
   int numberOfSubtitles = 0;
   for (Stream s : conversionSetting.getFfProbe().getStreams()) {
     if (CODEC_TYPE_SUBTITLE.equals(s.getCodec_type())
         && !INVALID_SUBTITLE.equals(s.getCodec_name())) {
       numberOfSubtitles++;
     }
   }
   return numberOfSubtitles;
 }
  private String[] internalGetSubtitle(int position) {

    Stream subtitle = null;

    int subtitleIndex = 0;

    for (int streamIndex = 0;
        streamIndex < conversionSetting.getFfProbe().getStreams().size();
        streamIndex++) {
      Stream s = conversionSetting.getFfProbe().getStreams().get(streamIndex);
      if (CODEC_TYPE_SUBTITLE.equals(s.getCodec_type())
          && !INVALID_SUBTITLE.equals(s.getCodec_name())) {

        if (position == subtitleIndex) {
          subtitle = s;
        }

        subtitleIndex++; // increment for all valid subtitles
      }
    }

    if (subtitle == null) return null;

    // get the language code for the filename
    String language = null;
    Tags t = subtitle.getTags();
    if (t != null) {
      language = t.getLanguage();
    }

    if (language == null) language = "DEFAULT";

    File fileName = conversionSetting.getSubtitleFileName(language);

    ArrayList<String> cmd = new ArrayList<String>();
    cmd.add("ffmpeg");
    cmd.add("-i");
    cmd.add(conversionSetting.getOriginalVideoFile().getAbsolutePath());
    cmd.add("-vn");
    cmd.add("-an");
    cmd.add("-map");
    cmd.add("0:s:" + position);
    cmd.add(fileName.getAbsolutePath());

    return getArray(cmd);
  }
  private void addAudioConversion(List<String> cmd) {
    cmd.add("-c:a");
    cmd.add("libfdk_aac");

    /*
    High Efficiency profile is giving trouble for some encodings.
    e.g.: pcm_s16le, 8000 Hz, 1 channels, s16, 128 kb/s (video from a mini camera I have)
     */
    // cmd.add("-profile:a");
    // cmd.add("aac_he");
    cmd.add("-cutoff");
    cmd.add("18000");

    boolean bitRateAdded = false;
    Stream audioStream = getStream(CODEC_TYPE_AUDIO);
    String audioBitRate = audioStream.getBit_rate();

    if (audioBitRate == null || audioBitRate.trim().length() == 0) {
      // if it doesn't have, just let FFMPEG do its default thing
      bitRateAdded = true;
    } else {
      try {
        long abr = Long.parseLong(audioBitRate);
        if (abr
            > Settings.getMaxPerChannelAudioBitRate(conversionSetting)
                * audioStream.getChannels()) {
          bitRateAdded = true;
          cmd.add("-b:a");
          cmd.add(
              Long.toString(
                  Settings.getMaxPerChannelAudioBitRate(conversionSetting)
                      * audioStream.getChannels()));
        }
      } catch (Exception e) {
        /* number format */
      }
    }

    if (!bitRateAdded) {
      cmd.add("-b:a");
      cmd.add(audioBitRate);
    }
  }
  //
  // general information about this file
  // =================================================================================================================
  private int internalGetType() {

    Stream videoStream = getStream(CODEC_TYPE_VIDEO);
    if (videoStream == null) return TYPE_NO_GOOD;

    Stream audioStream = getStream(CODEC_TYPE_AUDIO);
    if (audioStream == null) return TYPE_NO_GOOD;

    // good video codec and profile
    if (VIDEO_CODEC.equals(videoStream.getCodec_name())
        && VIDEO_PROFILE.equals(videoStream.getProfile())) {

      // good audio codec
      if (AUDIO_CODEC_1.equals(audioStream.getCodec_name())
          || AUDIO_CODEC_2.equals(audioStream.getCodec_name())) {

        // good container
        String ext =
            FilenameUtils.getExtension(conversionSetting.getOriginalVideoFile().getAbsolutePath());
        if (MP4.equals(ext)
            && conversionSetting.getFfProbe().getFormat().getFormat_name().contains(MP4)) {
          return TYPE_NO_CHANGE;
        }

        return TYPE_JUST_CHANGE_CONTAINER;
      }

      return TYPE_CONVERT_ONLY_AUDIO;
    }

    // same file size uses 2 pass, other qualities uses CRF
    return conversionSetting.getQuality() == Settings.QUALITY_SAME_FILE_SIZE
        ? TYPE_TWO_PASS
        : TYPE_CRF;
  }