0

我試圖用MediaProjection API記錄屏幕。我想修剪媒體投影錄製的視頻。有沒有辦法做到這一點,而不使用任何第三方依賴?如何使用MediaCodec修剪視頻

+0

你找到一個解決辦法? –

+0

不確定MediaProjection會話的輸出是什麼,但MediaCodec是要走的路。旅程從這裏開始:https://stackoverflow.com/questions/20468211/use-mediacodec-and-mediaextractor-to-decode-and-code-video –

+0

@martynmlostekk是的,我找到了一個。我會將其作爲回答張貼 – vezikon

回答

1

經過大量的挖掘,我發現這個片段

/** 
* @param srcPath the path of source video file. 
* @param dstPath the path of destination video file. 
* @param startMs starting time in milliseconds for trimming. Set to 
*     negative if starting from beginning. 
* @param endMs end time for trimming in milliseconds. Set to negative if 
*     no trimming at the end. 
* @param useAudio true if keep the audio track from the source. 
* @param useVideo true if keep the video track from the source. 
* @throws IOException 
*/ 
@TargetApi(Build.VERSION_CODES.LOLLIPOP) 
private static void genVideoUsingMuxer(String srcPath, String dstPath, 
             int startMs, int endMs, boolean useAudio, boolean 
                useVideo) 
     throws IOException { 
    // Set up MediaExtractor to read from the source. 
    MediaExtractor extractor = new MediaExtractor(); 
    extractor.setDataSource(srcPath); 
    int trackCount = extractor.getTrackCount(); 
    // Set up MediaMuxer for the destination. 
    MediaMuxer muxer; 
    muxer = new MediaMuxer(dstPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 
    // Set up the tracks and retrieve the max buffer size for selected 
    // tracks. 
    HashMap<Integer, Integer> indexMap = new HashMap<>(trackCount); 
    int bufferSize = -1; 
    for (int i = 0; i < trackCount; i++) { 
     MediaFormat format = extractor.getTrackFormat(i); 
     String mime = format.getString(MediaFormat.KEY_MIME); 
     boolean selectCurrentTrack = false; 
     if (mime.startsWith("audio/") && useAudio) { 
      selectCurrentTrack = true; 
     } else if (mime.startsWith("video/") && useVideo) { 
      selectCurrentTrack = true; 
     } 
     if (selectCurrentTrack) { 
      extractor.selectTrack(i); 
      int dstIndex = muxer.addTrack(format); 
      indexMap.put(i, dstIndex); 
      if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) { 
       int newSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE); 
       bufferSize = newSize > bufferSize ? newSize : bufferSize; 
      } 
     } 
    } 
    if (bufferSize < 0) { 
     bufferSize = DEFAULT_BUFFER_SIZE; 
    } 
    // Set up the orientation and starting time for extractor. 
    MediaMetadataRetriever retrieverSrc = new MediaMetadataRetriever(); 
    retrieverSrc.setDataSource(srcPath); 
    String degreesString = retrieverSrc.extractMetadata(
      MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION); 
    if (degreesString != null) { 
     int degrees = Integer.parseInt(degreesString); 
     if (degrees >= 0) { 
      muxer.setOrientationHint(degrees); 
     } 
    } 
    if (startMs > 0) { 
     extractor.seekTo(startMs * 1000, MediaExtractor.SEEK_TO_CLOSEST_SYNC); 
    } 
    // Copy the samples from MediaExtractor to MediaMuxer. We will loop 
    // for copying each sample and stop when we get to the end of the source 
    // file or exceed the end time of the trimming. 
    int offset = 0; 
    int trackIndex = -1; 
    ByteBuffer dstBuf = ByteBuffer.allocate(bufferSize); 
    MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); 
    try { 
     muxer.start(); 
     while (true) { 
      bufferInfo.offset = offset; 
      bufferInfo.size = extractor.readSampleData(dstBuf, offset); 
      if (bufferInfo.size < 0) { 
       InstabugSDKLogger.d(TAG, "Saw input EOS."); 
       bufferInfo.size = 0; 
       break; 
      } else { 
       bufferInfo.presentationTimeUs = extractor.getSampleTime(); 
       if (endMs > 0 && bufferInfo.presentationTimeUs > (endMs * 1000)) { 
        InstabugSDKLogger.d(TAG, "The current sample is over the trim end time."); 
        break; 
       } else { 
        bufferInfo.flags = extractor.getSampleFlags(); 
        trackIndex = extractor.getSampleTrackIndex(); 
        muxer.writeSampleData(indexMap.get(trackIndex), dstBuf, 
          bufferInfo); 
        extractor.advance(); 
       } 
      } 
     } 
     muxer.stop(); 

     //deleting the old file 
     File file = new File(srcPath); 
     file.delete(); 
    } catch (IllegalStateException e) { 
     // Swallow the exception due to malformed source. 
     InstabugSDKLogger.w(TAG, "The source video file is malformed"); 
    } finally { 
     muxer.release(); 
    } 
    return; 
} 
+0

基於此片段,它只修剪到關鍵幀,不是嗎?我們可以在關鍵幀之後向複用器提供任何樣本數據,以便它可以從任何B幀開始? –