티스토리 뷰

크리에이티브 커먼즈 라이선스
Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시 2.0 대한민국 라이선스에 따라 이용하실 수 있습니다.
본문

 Android API 중 4.1부터 추가된 API인 MediaCodec이 있습니다. Android 4.3 부터 추가 API인 MediaMuxer가 추가되었고, Surface를 통한 인코딩 기능이 사용가능합니다. MediaCodec과 MediaMuxer에 대한 간단한 설명을 작성하고, 주요 API에 대한 설명을 작성합니다.


Android API

 - MediaCodec

 - MediaMuxer

 - MediaExtractor



MediaCodec

 - Android 4.1 이상에서 제공됩니다.

 - raw byte를 이용하여 인코딩/디코딩을 직접 처리할 수 있는 API 입니다.

 - Android 4.3 부터 MediaMuxer를 이용하여 MP4 파일을 출력할 수 있습니다.

 - Android 4.3 부터 Surface를 이용하여 인코딩이 가능합니다.

 - Android 4.3 부터 VP8, VP9 인코딩/디코딩 가능합니다.

 - MediaExtractor를 이용하여 파일을 열고, 디코딩이 가능합니다.



MediaMuxer

 - Android 4.3 이상에서 제공됩니다.

 - MediaCodec과 함께 사용해야 합니다.

 - 현재는 MP4 파일 output이 가능합니다.



MediaCodec 지원 가능한 코덱 - Video

 일부 코덱은 SW코덱으로 동작합니다.

  • "video/x-vnd.on2.vp8" - VP8 video (i.e. video in .webm)
  • "video/x-vnd.on2.vp9" - VP9 video (i.e. video in .webm)
  • "video/avc" - H.264/AVC video
  • "video/mp4v-es" - MPEG4 video
  • "video/3gpp" - H.263 video


MediaCodec 지원 가능한 코덱 - Audio

 일부 코덱은 SW코덱으로 동작합니다.

  • "audio/3gpp" - AMR narrowband audio
  • "audio/amr-wb" - AMR wideband audio
  • "audio/mpeg" - MPEG1/2 audio layer III
  • "audio/mp4a-latm" - AAC audio (note, this is raw AAC packets, not packaged in LATM!)
  • "audio/vorbis" - vorbis audio
  • "audio/g711-alaw" - G.711 alaw audio
  • "audio/g711-mlaw" - G.711 ulaw audio



MediaCodec 사용하기

 MediaCodec을 이용하여 H.264를 인코딩 디코딩 할 수 있습니다. 이 H.264 인코딩에 사용되는 색공간은 YUV 입니다. YUV 색공간 중 안드로이드에서 인코딩/디코딩 가능한 색공간은 NV12와 I420 을 사용합니다. Surface를 사용할 경우 RGB 데이터를 사용하면 되지만 RGB가 아닌 경우에는 YUV를 직접 변환하는 작업이 필요합니다.


 YUV로 변환하는 작업을 위한 라이브러는 libYUV를 사용하시는것을 추천드립니다. Android Full Source에 포함되어 있는것을 사용하셔도 되고, 별도로 다운로드 받아 설치하셔도 됩니다.

 libYUV : https://code.google.com/p/libyuv/


이미지 출처 : Wikipedia YUV



MediaCodec 초기화

 MediaCodec을 초기화 하기 위한 코드로 아래와 같이 초기화 합니다. createDecoderByType 또는 createEncoderByType를 이용하여 Codec을 MediaCodec 객체를 생성합니다. 여기에서 말하는 Type은 MediaCodec의 지원 코덱 이름이 됩니다.

MediaCodec codec = MediaCodec.createDecoderByType(type);



 Codec을 configure를 통해 Surface 초기화와 Media 암호화, flags를 사용합니다.

 MediaFormat : 인코딩/디코딩에 따라서 초기화 하는 코드가 다르게 됩니다. 간단하게 인코딩시에 설정해야 할 Format을 살펴보겠습니다.

 Surface : Surface의 경우는 디코딩시에만 적용하시면 됩니다. 디코딩시 Surface를 적용하면 화면 랜더링을 포함하여 출력되게 됩니다.

 flags : 인코딩과 디코딩 flags를 지정해주어야 합니다. 인코딩시에는 MediaCodec.CONFIGURE_FLAG_ENCODE을 지정하고, 디코딩 시에는 0을 설정하면 됩니다.

codec.configure(format, …);
public void configure (MediaFormat format, Surface surface, MediaCrypto crypto, int flags);


Video 인코딩 시 MediaFormat

 이 중 Color format은 스마트폰마다 색상값이 달라지게 됩니다. 별도의 코드를 이용하여 색상값을 찾도록 해야 합니다.

MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", 320, 240);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 125000);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar);
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);


 MediaFormat을 초기화 할 경우 안드로이드 기기의 색상값 확인이 필요합니다. Android의 색상값별로 구분을 하면 아래와 같습니다.(참고 : https://gist.github.com/bryanwang/7380901)

  • COLOR_FormatYUV420Planar (I420)
  • COLOR_FormatYUV420PackedPlanar (also I420)
  • COLOR_FormatYUV420SemiPlanar (NV12)
  • COLOR_FormatYUV420PackedSemiPlanar (also NV12)
  • COLOR_TI_FormatYUV420PackedSemiPlanar (also also NV12)


H.264의 경우의 코드이며 아래와 같은 코드로 색상값을 확인할 수 있습니다.


selectCodec 코드는 API의 http://developer.android.com/reference/android/media/MediaCodecInfo.html 를 참고하시면 됩니다.

/**
 * Returns the first codec capable of encoding the specified MIME type, or
 * null if no match was found.
 */
private MediaCodecInfo selectCodec(String mimeType) {
	int numCodecs = MediaCodecList.getCodecCount();
	for (int i = 0; i < numCodecs; i++) {
		MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);

		if (!codecInfo.isEncoder()) {
			continue;
		}

		for (String type: codecInfo.getSupportedTypes()) {
			if (type.equalsIgnoreCase(mimeType)) {
				Log.i("selectCodec", "SelectCodec : " + codecInfo.getName());
				return codecInfo;
			}
		}
	}
	return null;
}

/**
 * Retruns a color format that is supported by the codec and by this test
 * code. If no match is found, this throws a test failure -- the set of
 * formats known to the test should be expanded for new platforms.
 */
protected int selectColorFormat(String mimeType) {
	MediaCodecInfo codecInfo = selectCodec(mimeType);
	if (codecInfo == null) {
		throw new RuntimeException("Unable to find an appropriate codec for " + mimeType);
	}
	
	MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType);
	for (int i = 0; i < capabilities.colorFormats.length; i++) {
		int colorFormat = capabilities.colorFormats[i];
		if (isRecognizedFormat(colorFormat)) {
			Log.d("ColorFomar", "Find a good color format for " + codecInfo.getName() + " / " + mimeType);
			return colorFormat;
		}
	}
	return -1;
}

/**
 * Returns true if this is a color format that this test code understands
 * (i.e. we know how to read and generate frames in this format).
 */
private boolean isRecognizedFormat(int colorFormat) {
	switch (colorFormat) {
	// these are the formats we know how to handle for this test
	case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
	case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar:
	case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
	case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar:
	case MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar:
		return true;
	default:
		return false;
	}
}


Audio 인코딩 시 MediaFormat

MediaFormat format  = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 8000);
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
format.setInteger(MediaFormat.KEY_BIT_RATE, 128000);

초기화가 완료되면 Codec를 start하면 됩니다.

codec.start();



MediaMuxer 초기화

 MediaMuxer는 파일이름과 OUTPUT Type을 지정하면 됩니다.

MediaMuxer muxer = new MediaMuxer("temp.mp4", OutputFormat.MUXER_OUTPUT_MPEG_4);



MediaCodec과 MediaMuxer 인코딩 예제

 MediaCodec과 MediaMuxer를 함께 사용하기 위한 예제입니다. MediaCodec의 InputBuffer와 OutputBuffer를 생성해야 합니다.

ByteBuffer[] inputBuffers = codec.getInputBuffers();
ByteBuffer[] outputBuffers = codec.getOutputBuffers();


 생성된 InputBuffer가 1개 이상이기 때문에 dequeueInputBuffer를 통하여 사용가능한 TempBuffer의 Number를 가져와 처리해야 합니다. 그리고 Buffer를 put 하고, queueInputBuffer를 추가하면 됩니다.


 queueInputBuffer의 원문은 아래와 같습니다. index는 dequeueInputBuffer에서 return된 번호이며, offset은 입력된 Byte의 offset 입니다. 기본적으로는 0을 지정하시면 됩니다. 입력해서 넣어주는 Buffer의 크기를 지정하고, presentationTimeUs는 마이크로 초를 입력하시면 됩니다. 동기화를 위한 시간으로 Muxer를 사용할 경우에는 꼭 추가해야 합니다.

 flags는 기본은 0으로 작업하시면 되며, MediaCodec API를 참고하셔서 추가하시면 됩니다.

public final void queueInputBuffer (int index, int offset, int size, long presentationTimeUs, int flags)


InputBuffer 예제

int inputBufferIndex = codec.dequeueInputBuffer(timeoutUs);
if (inputBufferIndex >= 0) {
  // fill inputBuffers[inputBufferIndex] with valid data
  ...
  codec.queueInputBuffer(inputBufferIndex, ...);
}


OutputBuffer 예제

 OutputBuffer 예제로 해당 가이드라인 코드는 MediaMuxer를 함께 사용하기 위한 코드를 추가하였습니다. MediaMuxer를 사용하기 위해서는 BufferInfo class를 함께 사용해야 합니다. InputBuffer과 마찬가지로 dequeueOutputBuffer 를 통하여 OutputBuffer Index를 return 받아 처리하면 됩니다.


BufferInfo bufferInfo = new BufferInfo();
int outputBufferIndex = codec.dequeueOutputBuffer(bufferInfo, timeoutUs);
if (outputBufferIndex >= 0) { // 0 이상일 경우에 인코딩/디코딩 데이터가 출력됩니다.
ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
// muxer에 Sample data를 입력합니다.(파일로 저장)
muxer.writeSampleData(outputBufferIndex, outputBuffer, bufferInfo);
// outputBuffer is ready to be processed or rendered.
// release OutputBuffer의 2번째 boolean 값은 Surface를
// 통한 디코딩시에 true, 그렇지 않으면 false 처리합니다.
codec.releaseOutputBuffer(outputBufferIndex, true/false);

} else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
// Output buffer changed가 호출되면 outputBuffers 를 다시 호출합니다.(Temp buffer의 수가 변경될 수 있음)
outputBuffers = codec.getOutputBuffers();

} else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
 // More often, the MediaFormat will be retrieved from MediaCodec.getOutputFormat()
// or MediaExtractor.getTrackFormat().

// Muxer를 초기화 필요할 경우 아래와 같은 코드를 추가해주면 됩니다. 
// Audio/Video를 모두 Muxer에 추가할 경우 2개를 아래와 같이 따로 따로 추가해야 하며,
// Codec 역시 2개를 별도로 생성해주어야 합니다.
MediaFormat audioFormat = audioCodec.getOutputFormat();
MediaFormat videoFormat = videoCodec.getOutputFormat();
// MediaFormat에 따라서 Track을 추가하게되면, TrackIndex가 생성됩니다.
int audioTrackIndex = muxer.addTrack(audioFormat);
int videoTrackIndex = muxer.addTrack(videoFormat);
// 트랙 추가가 완료되면 start를 호출하여 muxer를 시작합니다.
muxer.start();
}



코덱 사용 종료

 코덱을 사용하였으면 stop, release 를 순서대로 호출하면 됩니다.

codec.stop();
codec.release();
codec = null;



Muxer 종료

 Muxer는 꼭 stop을 호출해줘야 합니다. MP4파일의 가장 중요한 head 정보가 쓰여지게 됩니다. stop이 완료되지 않으면 HEAD 정보가 포함되지 않아 재생이 불가능한 MP4 파일이 생성이 되게 됩니다.

muxer.stop();
muxer.release();
muxer = null;



마무리

 간단하게 MediaCodec과 MediaMuxer API를 살펴보았습니다. 추후에 MediaCodec과 MediaMuxer를 사용하는 예제를 작성할 예정이며, Audio를 byte를 통하여 디코딩할경우의 예제는 아래 글을 참고하시면 됩니다.


 Video를 byte를 통한 직접 디코딩하는것과는 좀 다르게 별도의 코덱 정보를 추가로 작성해주어야 합니다. 이에 대한 예제 코드를 담고 있으며, 가져다가 사용하시면 됩니다.


MediaCodec AAC 디코딩 하기 : http://thdev.net/567

개인 광고 영역


댓글
  • 프로필사진 BlogIcon 임다솜 컴퓨터공학과 4학년학생입니다. 프로젝트를 하며 미디어 먹서를 사용해서 실시간 영상에서 나오는 데이터를 파일화 하는 구현을 해야 했습니다. 굉장히 막막했는데 이 글을 보고 천천히, 꼼꼼히 따라하다보니 어려울 것만 같던 먹싱에 성공하게 되었습니다. 비디오, 오디오 모두 정말정말정말! 좋은 글 감사합니다!! 2015.12.11 13:51 신고
  • 프로필사진 BlogIcon taehwan 도움이 되었다니 다행이네요! ㅎㅎ 어렵지 않습니다. 직접 구현하는게 아니니... EXOPlayer 라는 오픈소스도 있으니 참고해보세요! 2015.12.13 23:14 신고
  • 프로필사진 초보 미디어 코덱으로 화면 출력까지 성공했는데
    좌우반전을 못시키겠네요..
    2015.12.28 11:33 신고
  • 프로필사진 BlogIcon taehwan 음 OpenGL 을 이용하셔서 직접.. 반전 시키셔야 할거에요.
    MediaCodec을 이용해서 디코딩 하셔야 하는 이유가 없으시다면 ExoPlayer 를 사용하셔도
    2015.12.29 22:28 신고
  • 프로필사진 초보 미디어코덱을 surfaceview를 이용하는데 그럼 glsurfaceview를 이용할시 미디어 코덱으로 좌우반전도 가능한가요?
    시도해보고있는데 decoder.configure(format, surface, null, 0)
    이 설정부분에서 surface올리는게 자꾸 release 가 이미되어있다고 에러나네요.

    미디어 코덱도 YUV형식이니깐 바이트버퍼로 데이터를 저장시에 YUV 형식의 데이터로 보낼수있는지요,,.
    exoplayer보니깐 YUV데이터를 바이트버퍼데이터를 처리해서 출력하는거같더라고요.
    2015.12.30 11:35 신고
  • 프로필사진 BlogIcon taehwan ExoPlayer를 사용하시는것과.. 직접 GLSurface를 이용하여 구현하는것.. 모두 동일합니다...
    ExoPlayer도 MediaCodec을 이용하고 있어서... 다른 부분은 없습니다.
    GLSurface를 사용하시게 되면.. GLSurface 생성하는 부분의 Surface 객체를 넘겨주시면 됩니다.

    YUV 데이터를 바이트로 직접 받는건 가능합니다. Surface를 사용하지 않으시면 가능하니깐요. 이때의 문제점은 기기별로 YUV 색상값이 다르게 나옵니다.
    크게 I420과 NV12 2가지로 나옵니다.(안드로이드 상에서는)

    참고로 YUV로 압축하더라도 수많은 YUV 압축 방식을 가집니다. 그걸 하나하나 대응하지는 못합니다.
    2015.12.30 21:55 신고
  • 프로필사진 절좀살려주십쇼 제가 동영상에 워터마크를 올려서 파일로 만들고 싶은데...
    도저히 감이 안잡힙니다...
    현재는 영상만 만들수 있는 수준이네요 ㅠㅠㅠ 제발 어떻게 구현해야 하는지 팁좀 주시기 바랍니다 ㅠㅠ
    순서를 써주시면 더 좋고 ㅠㅠ
    2016.04.19 16:53 신고
  • 프로필사진 BlogIcon taehwan 안녕하세요.

    일단 진행할 수 있으신 순서를 대략적으로 설명 드리겠습니다.

    - MediaCodec을 이용하기 위한 GLSurface를 이용합니다.
    - GLSurface을 이용하시면 Texture 처리를 할 수 있습니다.
    - Texture은 여러개를 처리할 수 있습니다. (OpenGL ES 2.0또는 3.0을 이용하시면 되겠고, 2.0의 자료가 많을겁니다.)
    - Texture을 여러개 생성하여 하나는 백그라운드(화면의 영상), 또 다른 하나는 워터마크를 올리시면 됩니다.

    다시 정리하면
    - 필요 기술
    OpenGL ES 2.0 또는 3.0
    GLSurface(OpenGL을 사용하기 위함)/TextureView
    MediaCodec

    ------
    GLSurface를 생성하고, Texture을 2개 만드세요.
    1개는 화면의 영상을 담을 Texture이고,
    또 다른 하나는 워트마크를 담을 Texture 입니다.

    생성된 Surface를 MediaCodec의 초기화시에 surface를 적용하시면 됩니다.

    참고로 기본 GLSurface을 이용하여 디/인코딩 하는 예제가 존재합니다.
    http://bigflake.com/mediacodec/
    참고하시면 도움이 되실것 같습니다.

    OpenGL ES 다루는 방법도 찾으셔야합니다....
    2016.04.20 21:16 신고
  • 프로필사진 LIM 잘보았습니다.
    mediacodec과 extractor를 이용하면서 실시간으로 yuv 데이터를 얻었는데요.

    디코딩을 해야 프렝미을 얻을수있어서 decoder.configure(format, null, null, 0);
    이로하였고
    이 렇게 구한 프레임을 5장씩 건너서 인코딩을 하려고합니다

    그런데 글에서는 encoding 될때 decoder.configure(format, null, null, 1); 로되어야하는데요, (API 문서에서도)
    디코딩에서 구한 byteBuffer를 바로 muxer에 쓸수없나요?

    2 . 위에서 구한 Frame을 5장씩 건너띄어서 surface에 보여주려하는데
    기존같은경우 encoder에서 surface를 넣어줘서 진행하였는데요.

    저렇게 5장씩 건너서 하려면, decoding되는게 다보여지기떄문에 configure를 사용하면 불가능할거같은데.

    따로 surface에 뿌리는 방법이 없나요? 그냥 GLES 로 texture로 뿌리는게 답일까요?

    고민을 이것저것해봐도 어느게 좋을 지 모르고 잘 알지 못하여 질문드립니다.

    글은 잘 읽었습니다 :D
    2016.10.18 23:18 신고
  • 프로필사진 BlogIcon taehwan 안녕하세요.

    질문을.. 앞에서 주셨었는데... 다시 하신것 같네요...

    질문이 이게 맞는건지요...

    5장을 뛰어넘어서 Encoder를 하고 싶다....

    SurfaceView로 처리하셔야 하구요?

    그러면 다음과 같이 하실 수 있겠죠..

    1. GLSurface를 합니다.
    - EGL로 하셔야 합니다. 눈에 보이는 화면이 아닌 보이지 않는 화면으로 구성하셔야 합니다.

    그 자료는.. http://thdev.net/577 PPT를 참고하시면 됩니다.
    - 구글 CTS 테스트 코드에 모두 포함되어 있습니다.

    2. Muxer에는 그냥 저장하시면 의미 없습니다.

    디코딩이 된 데이터는 NV21/I420의 색상값을 가지는 그냥 단순 데이터입니다. 압축된 데이터가 아니기에 Muxer에 저장할 수 없죠. 안드로이드의 Muxer에서는 MediaCodec Encoder 데이터를 가져와야 합니다.

    그리고 다시...

    기존 영상의 5프레임을 건너뛴 연상을 그냥 해당 프레임만 file로 저장하시면 이상한 이미지가 나옵니다.

    우선 동영상에 대한 기본 개념을 찾아보시고 작업하시면 좋을것 같습니다.....(앞에 추가해드린 링크에 대부분? 포함이 되어 있긴합니다.)
    2016.10.23 21:07 신고
  • 프로필사진 최진호 안녕하세요~ MediaMuxer가 4.3부터인데 그 전에는 영상 만들어주는게 없었나요? 지금 만드는 어플리케이션이 4.1부터 지원되는데 어떻게 해야할지 고민되네요... 찾아보려고 했는데 안 나오고 뭐라 쳐야 잘 나올지 감도 안 잡히네요 ㅠㅠ 2017.05.25 22:36 신고
  • 프로필사진 BlogIcon taehwan 4.1부터 지원하시려면 MediaCodec의 제한도 큽니다. SW 코덱인 그나마 접근하기 쉬운 FFMPEG을 다루어보시는 방법으로 접근해야 합니다.

    지금 굳이 4.1부터 지원하실 필요는 사실 없겠지만.. 직접 인코딩을 해야 한다면 ffmpeg으로 접근하셔야 하구요.(Muxer와 DeMuxer 코덱 모두 지원합니다.(다만 성능은 안좋겠죠))

    4.3이상부터는 MediaCodec을 이용해서 하드웨어 인코딩을 하시고, 이를 Muxer를 이용하는 방법도 가능합니다.

    또는
    4.1부터 모두 MediaCodec으로 인코딩 하시구요. 이를 ffmpeg에서의 Muxer를 이용하시거나 OpenSource로 만들어지느 mp4 muxer들이 많이 있습니다. 이를 활용하시는걸 추천드립니다.
    2017.05.26 13:38 신고
  • 프로필사진 폭폭배 와.. 음성은 녹음하면서 영상이미지는 사진한장으로 할수는 없나요? 카메라안쓰구 2018.03.16 16:39 신고
  • 프로필사진 BlogIcon taehwan 만드시면 가능하죠. 카메라에서 첫번째 장을 동영상으로 처리하고, 음성만 계속 추가하는거면 가능합니다. 2018.03.16 22:21 신고
  • 프로필사진 gong 안녕하세요~ 올려주신 자료들 잘 보았습니다. 제가 동영상에 비가청 주파수를 합칠려고하는데 가능할까요?? 2018.05.27 16:11 신고
  • 프로필사진 BlogIcon taehwan 네 가능하긴 합니다. 디코딩/인코딩을 하지 않고 단순히 합칠 수도 있는데 조건은 mp3/aac만 가능합니다. 다만 모바일에서는 aac만 가능하실거에요. 2018.05.27 18:09 신고
  • 프로필사진 gong 죄송한데 제가 아무지식없이 어플을 제작할려다보니 잘몰라서 그런데 단순히 합친다는 말씀이 위에 코덱 클래스를 사용하지 않고 말씀하시는건가요? 혹시 그렇다면 어떠한 클래스를 사용해야 할까요?? 죄송합니다 ㅠㅠ 2018.05.27 19:50 신고
  • 프로필사진 BlogIcon taehwan 자세하게 코드까지 설명드리긴 힘들고, MediaExtractor로 파일을 열고, MediaMuxer로 합치는 방법을 사용할 수 있을것 같네요. 2018.05.27 20:42 신고
  • 프로필사진 gong 네 감사합니다! 열심히 찾아보면서 하겠습니다!
    2018.05.27 20:47 신고
  • 프로필사진 gong 위 비가청 주파수 질문한 학생입니다.
    제가 영상의 사운드랑 비가청 주파수 사운드랑 mediaextractor 랑 mediamuxer 를 이용해서 오디오를 합치는 것을 하는데 두개가 동시에 재생되게 하나의 파일로 합치는게 가능한가요? 계속 시도해 보고있는 데 잘안되서 질문드립니다!
    2018.06.09 21:23 신고
  • 프로필사진 BlogIcon taehwan 타임스탬프가 있어야 재생이 동작합니다. 2018.06.14 13:21 신고
  • 프로필사진 choo 제가 음성인식(구글클라우스서비스)에서 byte 단위로 음성데이터를 받아서 m4a인코딩로 인코딩 했습니다. 근데 약 1.5배 정도 느리게 들립니다.
    혹시 속도를 느리게 인코딩 할수 있는지 궁금합니다. 조언이라도 감사합니다.
    참고로 음성데이터는 16000hz 샘플레이터로 받고 16000hz샘플레이트 에 64000bit로 샘플링, 그리고 1채널로 인코딩 했습니다.
    2018.06.22 13:10 신고
  • 프로필사진 BlogIcon taehwan 안녕하세요. 샘플링의 정보가 변경되었기에 느려진것입니다. 160000 -> 64000으로 변경하신거에요. 같은등급으로하시면 돌아오게됩니다. 2018.06.25 23:46 신고
댓글쓰기 폼
Total
5,174,837
Today
165
Yesterday
1,323
«   2018/08   »
      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  
글 보관함