Android 로 컬 비디오 압축 프로젝트 의 예제 코드

머리말
본 고 는 초 에 찍 은 짧 은 동 영상 녹화 가 아니 라 사용자 가 현지의 기 존 동 영상 을 선택 하여 압축 하여 업로드 하 는 것 을 토론 한다.초 촬영 의 실현 은 사실 사용자 정의 영상 녹화 기능 으로 녹화 시간,해상도,인 코딩 률 등 을 제어 하고 부피 가 작은 영상 을 생 성하 여 업로드 하 는 것 이다.그러나 우 리 는 원래 영상의 인 자 를 제어 할 수 없 기 때문에 아마도 매우 큰 영상 일 것 이다.압축 처리 가 필요 할 것 이다.
사고의 방향
ffmpeg 를 이용 하여 영상 코드 를 바 꾸 고 매개 변 수 를 설정 하여 해상도 와 인 코딩 률 이 더 작은 영상 을 생 성하 여 압축 을 실현 합 니 다.물론 ffmpeg 의 기능 은 이 뿐만 이 아니 라 매우 큰 주제 이다.
사 용 된 소스 라 이브 러 리:https://github.com/WritingMinds/ffmpeg-android-java
사용 방법
기본 원리:안 드 로 이 드 환경 에서 실행 가능 한 파일 ffmpeg 을 로 컬 에 저장 하고 코드 는 ffmpeg 의 압축 명령 을 실행 합 니 다.

//     asset   ffmpeg     ,    app data/data/files  

FFmpeg.getInstance(this).loadBinary(null);
이 방법 은 비동기 실행 이기 때문에 응용 프로그램 에서 실행 하 는 것 이 가장 좋다.방법 은 실행 성공 여부 의 반전 이 있 습 니 다.여 기 는 null 에 들 어가 결과 에 관심 이 없습니다.실행 이 끝나 면 핸드폰 의 디 렉 터 리 를 보 세 요.

실행 가능 한 파일 이 라면 안 드 로 이 드 셸 환경 에서 실행 할 수 있 을 것 입 니 다.adb 셸 이 핸드폰 에 들 어가 서 보 세 요.(전 제 는 핸드폰 이 루트 권한 을 가 져 왔 다 는 것 입 니 다.)

ffmpeg 명령 실행:예 를 들 어 ffmpeg 의 현재 버 전 보기:./ffmpeg-version

이 어 코드 에서 ffmpeg 의 각종 명령 을 사용 할 수 있 습 니 다.명령 을 String[]에 쓰 고 fFmpeg.execute 를 호출 하면 됩 니 다.
비디오 파일 정보 가 져 오기

String[] command = new String[]{"-i", arg.filePath};
try {
      fFmpeg.execute(commands, new ExecuteBinaryResponseHandler(){
        @Override
        public void onStart() {}

        @Override
        public void onProgress(String message) {
          Log.e("dml", "onProgress: message is " + message);
        }

        @Override
        public void onFailure(String message) {
          Log.e("dml", "onFailure: message is " + message);
        }

        @Override
        public void onSuccess(String message) {
          Log.e("dml", "onSuccess: message is " + message);
        }

        @Override
        public void onFinish() {
          Log.e("dml", "onFinish: ");
        }
      });
    } catch (FFmpegCommandAlreadyRunningException e) {
      e.printStackTrace();
    }
압축 비디오:

String[] commands = new String[]{"-threads","1","-i", arg.filePath, "-c:v", "libx264","-crf","30","-preset", "superfast" ,"-y", "-acodec","libmp3lame",arg.thumbVideoPath};
fFmpeg.execute(commands, new ExecuteBinaryResponseHandler(){});
매개 변수 설명:
  • -threads:실행 스 레 드 수,1 단일 스 레 드 압축
  • -i:input 경로,비디오 파일 에 들 어 오 는 경로
  • -c:v:인 코딩 형식,일반적으로 libx 264
  • 을 지정 합 니 다.
  • -crf:인 코딩 품질,수치 범 위 는 0-51 이 고 기본 값 은 23 이 며 숫자 가 작 을 수록 동 영상 을 출력 하 는 질 이 높 습 니 다.여기 30 은 저희 가 테스트 를 통 해 얻 은 경험 치
  • 입 니 다.
  • -preset:코드 속도,ultrafast,superfast,veryfast,fast,medium,slow,slower,veryslow 와 placebo.ultrafast 인 코딩 속도 가 가장 빠 르 지만 압축 률 이 낮 아 생 성 된 파일 이 더 크 고 placebo 는 정반 대 입 니 다.x264 에서 가 져 온 기본 값 은 medium 입 니 다.설명 이 필요 한 것 은 preset 은 주로 인 코딩 의 속도 에 영향 을 주 고 인 코딩 된 결과 의 질 에 큰 영향 을 주지 않 는 다 는 것 이다.
  • -acodec:오디 오 인 코딩,일반적으로 libmp3lame
  • 을 사용 합 니 다.
  • arg.thumbVideo Path:마지막 으로 들 어 온 것 은 동 영상 압축 후 저 장 된 경로
  • 입 니 다.
  • -y:출력 할 때 출력 디 렉 터 리 에 존재 하 는 동명 파일 을 덮어 씁 니 다(이 인 자 를 추가 하지 않 으 면 덮어 쓰 지 않 습 니 다)
  • 문제 해결
    이 소스 라 이브 러 리 는 영상 압축 에 사용 되 는데 실제 개발 에 많은 문제 가 존재 하 므 로 아래 에서 일일이 해결 하 겠 습 니 다.
    1.압축 진행 피드백
    코드 변환 명령 을 실행 한 후,onProgress 는 문자열 을 계속 출력 할 뿐 이 며,텍스트 가 길 기 때문에 정규 표현 식 이 필요 합 니 다.
    
            @Override
            public void onProgress(String s) {
              Pattern timePattern = Pattern.compile("(?<=time=)[\\d:.]*");
              Scanner sc = new Scanner(s);
              String match = sc.findWithinHorizon(timePattern, 0);
              if (match != null) {
                String[] matchSplit = match.split(":");
                if (duration!= 0) {
                  float progress = (Integer.parseInt(matchSplit[0]) * 3600 +
                      Integer.parseInt(matchSplit[1]) * 60 +
                      Float.parseFloat(matchSplit[2])) / duration;
                  int showProgress = (int) (progress * 100);
                  if(showProgress>100){
                    showProgress = 100;
                  }
                  notify.compressProgress(getTag(),showProgress);
                }
              }
            }
    
    2.낮은 수치 로 영상 압축 이 커진다
    실제 원 질 이 떨 어 지 는 동 영상 이 압축 되면 서 부피 가 오히려 커 진 것 으로 나 타 났 다.
    처리 방법:압축 하기 전에 영상 추출 정보 에 대한 명령 을 먼저 실행 하고 1024 kb/s 이하 의 영상 은 압축 하지 않 습 니 다.
    
            @Override
            public void onProgress(String s) {
              //Log.d("dml","pre onProgress = " + s);
              if(s.contains("Stream #0:0")){
                String tem = s.substring(0, s.indexOf("kb/s"));
                String type ;
                int pos = tem.lastIndexOf(",");
                if (pos != -1) {
                  type = tem.substring(pos + 1,tem.length()).trim();
                  try {
                    Integer integer = Integer.parseInt(type);
                    if(integer > 1024){
                      pressV(fFmpeg);//    
                    }else {
                      //    ,       
                    }
                  }catch (Exception e){
                  }
                }
              }
            }
    
    또한 압축 에 성공 한 후 압축 된 파일 과 원본 파일 의 크기 를 검사 하고 커지 면 원본 파일 을 직접 사용 합 니 다.
    3.다 중 스 레 드 여러 동 영상 압축
    소스 라 이브 러 리 에서 ffmpeg 명령 을 실행 하 는 것 은 AsycTask 에서 실 행 됩 니 다.
    
    ffmpegExecuteAsyncTask = new FFmpegExecuteAsyncTask(command , timeout, ffmpegExecuteResponseHandler);
    ffmpegExecuteAsyncTask.execute();
    execute 방법 은 api 11 이후 직렬 방법 입 니 다.즉,오픈 소스 라 이브 러 리 가 단일 스 레 드 로 제한 되 었 습 니 다.
    다음 으로 변경:ffmpeg Execute AsyncTask.executeOnExecutor(Executors.newCached ThreadPool();다 중 스 레 드 사용 가능
    테스트 에서 여러 개의 동 영상 이 동시에 압축 되 고 휴대 전화 가 심하게 열 이 나 는 것 을 발견 하여 원 디자인 을 사용 하 는 것 을 강력 히 권장 합 니 다.
    4.압축 속도 와 품질
    휴대 전화의 성능 이 제한 되 어 있어 압축 영상 속도 가 그다지 이상 적 이지 않 아 PC 단 에서 포맷 공장 으로 코드 영상 을 압축 해도 그리 빠 르 지 않다.
    압축 의 질 은 그런대로 괜찮아 서 기본적으로 원본 영상 과 같은 선명 도 를 유지 할 수 있다.다음은 테스트 데이터:

    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기