๐ Amazon IVS Broadcast SDK: Android Guide ์์ ๋ ์์ธํ ๋ด์ฉ์ ํ์ธํ์ค ์ ์์ต๋๋ค!
IVS (Amazon Interactive Video Service)
AWS์์ ์ ๊ณตํ๋ ๊ด๋ฆฌํ ๋ผ์ด๋ธ ๋น๋์ค ์คํธ๋ฆฌ๋ฐ ์๋น์ค์ด๋ค.
์น์ด๋ ์ฑ์ ์ฝ๊ฒ ํตํฉํ ์ ์์ด AWS ์ฝ์์์ ์ฑ๋์ ์์ฑํ๊ณ , SDK๋ฅผ ์ด์ฉํด ๊ตฌํ๋ง ํด ์ค๋ค๋ฉด ๊ฐํธํ๊ฒ ๋ฒํผ ๋ช ๊ฐ๋ก ์ฑ - ์ฑ / ์ฑ - ์น ๋ฑ ๋ค์ํ ๋ฐฉ๋ฒ์ผ๋ก ์คํธ๋ฆฌ๋ฐํ๊ณ , ๋ ๊ทธ ์คํธ๋ฆฌ๋ฐ์ ์์ฒญํ ์ ์๋ค.
AWS IVS ์๋น์ค๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ์ฐ์ AWS ๊ณ์ ์ด ํ์ํ๋ค. ๊ณ์ ์์ฑ์ ๊ฒฐ์ ์๋จ ์ ๋ณด๋ฅผ ์ ๋ ฅํ๋ ๊ฒ ์ธ์๋ ๋ณดํธ์ ์ธ ํ์๊ฐ์ ๊ณผ์ ๊ณผ ๋์ผํ์ฌ ๊ทธ๋ฆฌ ์ด๋ ต์ง ์๊ธฐ๋ ํ๊ณ , ์์นํ๋ฉด ๊ธ๋ฐฉ ๋์ค๊ธฐ ๋๋ฌธ์ ์๋ตํ๋๋ก ํ๊ฒ ๋ค.
์ฌ๊ธฐ์ IAM์ด๋? ์๋ฒ๋, ์คํ ๋ฆฌ์ง ๋ฑ์ AWS ๋ฆฌ์์ค๋ค์ ํตํฉํ๊ณ ์์ ์ ์ผ๋ก ๊ด๋ฆฌํ๊ธฐ ์ํ AWS์ ์๋น์ค์ด๋ค.
ํ์๊ฐ์ ์ ๋ง์น๋ฉด AWS ROOT ๊ณ์ ์ ๋ถ์ฌ๋ฐ์ผ๋ฉฐ, ์ฐ๋ฆฌ๊ฐ IVS ์ฑ๋์ ์์ฑํ๊ณ SDK๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ IAM ์ฌ์ฉ์๋ฅผ ์์ฑํ๊ณ IVS ์ฑ๋ ์์ฑ์ ๋ํ ๊ถํ์ ์ฌ์ฉ์์๊ฒ ์ ๊ณตํ๋ค๋ ๋ด์ฉ์ ์ ์ฑ ์ ์ถ๊ฐํด ์ฃผ์ด์ผ ํ๋ค.
๋ฌด์จ ์๋ฆฌ์ธ์ง... ํ๋๋ ๋ชจ๋ฅด๊ฒ ๋ค?
๋ผ๊ณ ํ๋๋ผ๋ ๊ด์ฐฎ๋ค.
AWS์์๋ IVS ๊ด๋ จ IAM ๊ถํ ์ค์ ์ ๋ํ ๊ฐ์ด๋๋ฅผ ์น์ ํ๊ฒ ์ ๊ณตํ๊ณ ์๋ค! ์ด ๋จ๊ณ์์๋ ํด๋น ๊ฐ์ด๋๋ฅผ ๋ณด๋ฉฐ ์ฐจ๊ทผ์ฐจ๊ทผ ๊ทธ๋๋ก ๋ฐ๋ผ๊ฐ๊ธฐ๋ง ํ๋ฉด ๋๊ฒ ๋ค.
IVS ์๋น์ค์์๋ ์์ง ์๋ฒ์ ์คํธ๋ฆผ ํค๋ฅผ ์ฌ์ฉํ์ฌ ๋ผ์ด๋ธ ์คํธ๋ฆฌ๋ฐ์ ์์ํ๋ค. IVS ์ฑ๋์ ์ด์ ๊ฐ์ ๋ผ์ด๋ธ ์คํธ๋ฆฌ๋ฐ๊ณผ ๊ด๋ จ๋ ๊ตฌ์ฑ ์ ๋ณด๋ค์ ์ ์ฅํ๋๊ณณ์ด๋ผ๊ณ ๋ณด๋ฉด ๋๋ค.
๊ทธ๋์ ์ด๋ป๊ฒ ์์ฑํ๋?
์ด ๋ํ AWS์ ๊ฐ์ด๋๋ฅผ ์ฐธ๊ณ ํ์.
์ด๊ฑด ๋ด๊ฐ ์ค์ ๋ก ํ๋ก์ ํธ์ ์ฌ์ฉํ๊ณ ์๋ IVS ์ฑ๋์ด๋ค. (์ผ๋ถ ์ ๋ณด๋ ๋ธ๋ผ์ธ๋ ์ฒ๋ฆฌ)
์ฑ๋์ ์ฑ๊ณต์ ์ผ๋ก ์์ฑํ๊ฒ ๋๋ฉด ์ด๋ ๊ฒ ์คํธ๋ฆฌ๋ฐ์ ์ฌ์ฉ๋๋ ์ฌ๋ฌ ๊ตฌ์ฑ ์ ๋ณด๋ค์ด ์ ์ฅ๋๊ณ , ๋ผ์ด๋ธ ์คํธ๋ฆผ ํญ์ ํตํด ์ค์๊ฐ์ผ๋ก ์คํธ๋ฆฌ๋ฐ๋๋ ํ๋ฉด์ ํ์ธํด ๋ณผ ์ ์์ผ๋ฉฐ, ์คํธ๋ฆผ ์ธ์ ์์๋ ์ธ์ ์ผ๋ง๋ ์คํธ๋ฆฌ๋ฐ์ ์งํํ๋์ง ํ์ธํ ์ ์๋ค.
IVS ๊ฐ์ด๋์๋ ์ค๋ช ๋์ด ์์ง๋ง, ์ฑ๋์ ์์ฑํ ๋ ์ต์ ์ ์ ํํ๋ฉด ์คํธ๋ฆฌ๋ฐ ๋ผ์ด๋ธ ์์์ ๋ นํ๋ ํํ๋ก ์ ์ฅํ์ฌ ๋ณด๊ดํ ์๋ ์๋ค!
์ด์ ์ ๋ง๋ก ๊ธ์ ์ ๋ชฉ์ธ Android broadcast application ๊ตฌํ ์ค๋น๊ฐ ๋๋ฌ๋ค!
์ฝ๋๋ฅผ ํจ๊ป ์ฒจ๋ถํ๋ฉฐ ์ค๋ช
ํ ์์ ์ด๊ณ , AWS์์๋ SDK ์ฌ์ฉ์ ๋ํ ๊ฐ์ด๋ ๋ฐ demo app ์ฝ๋๋ฅผ ์ ๊ณตํ๋ ๊ด๋ จ ๋ด์ฉ์ด ๊ถ๊ธํ๋ค๋ฉด ํ์ดํผ๋งํฌ๋ฅผ ํตํด ์ดํด๋ณด๋ฉด ๋๊ฒ ๋ค.
์ฌ์ค AWS์์ ์ ๊ณตํ๋ android broadcast demo app ์ฝ๋(kotlin)๋ฅผ ๊ทธ๋๋ก ๊ฐ์ ธ๋ค ์ฌ์ฉํ์ฌ๋ ๋ฌด๋ฐฉํ๋ค.
๋ชจ๋์ build.gradle ํ์ผ์ ์๋ dependencies ๋ถ๋ถ์ ํ๋จ์ ์ฝ๋๋ฅผ ์ถ๊ฐํด ์ค๋ค.
dependencies {
implementation 'com.amazonaws:ivs-broadcast:1.4.0'
}
์ํ ์ ๋ฐ์ดํธ๋ ์คํธ๋ฆฌ๋ฐ ๋๋ฐ์ด์ค ๋ณ๊ฒฝ ์๋ฆผ, ์ค๋ฅ ๋ฐ ์ธ์ ์ค๋์ค ์ ๋ณด๋ฅผ ์์ ๊ฐ๋ฅํ ์ด๋ฒคํธ ๋ฆฌ์ค๋ ์ฝ๋์ด๋ค. ๋ฉ์ธ ์กํฐ๋นํฐ์์ ์คํํ ์์ ์ด์ด์ MainActivity.java ํ์ผ ์์ ํ๋จ์ ์ฝ๋๋ฅผ ์ถ๊ฐํด ์ฃผ์๋ค.
BroadcastSession.Listener broadcastListener = new BroadcastSession.Listener() {
@Override
public void onStateChanged(@NonNull BroadcastSession.State state) {
Log.d(TAG, "State=" + state);
}
@Override
public void onError(@NonNull BroadcastException exception) {
Log.e(TAG, "Exception: " + exception);
}
};
์คํธ๋ฆฌ๋ฐ์ ์์ํ๊ธฐ ์ํด์๋ ์ดํ๋ฆฌ์ผ์ด์ ์์ ์ฌ์ฉ์์๊ฒ ๋๋ฐ์ด์ค์ ์นด๋ฉ๋ผ ๋ฐ ๋ง์ดํฌ์ ์ก์ธ์คํ ์ ์๋ ๊ถํ์ ์์ฒญํด์ผ ํ๋ค. ๋ฐ๋ผ์ ์ฌ์ฉ์์๊ฒ ๋ถ์ฌ๋ ๊ถํ์ด ์๋์ง ํ์ธํ๊ณ , ์๋ค๋ฉด ๊ถํ์ ์์ฒญํ๋ ์ฝ๋๋ฅผ ๋์ผํ๊ฒ MainActivity.java ํ์ผ์ ์ถ๊ฐํด ์ค๋ค.
final String[] requiredPermissions = { Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO };
for (String permission : requiredPermissions) {
if (ContextCompat.checkSelfPermission(MainActivity.this, permission) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, requiredPermissions, 0x100);
break;
}
}
์คํธ๋ฆฌ๋ฐ์ ์ํ ๋ธ๋ก๋์บ์คํธ ์ธ์
์ ์์ฑํด ์ค๋ค.
ํ๋จ์ ์ฝ๋๋ ํ๋ฉด ์นด๋ฉ๋ผ๋ฅผ ์ฌ์ฉํ ์คํธ๋ฆฌ๋ฐ์ ์ํ ๋ ์ถ๊ฐํ๋ฉด ๋๋ ์ฝ๋์ด๋ค.
Context ctx = getApplicationContext();
BroadcastSession broadcastSession = new BroadcastSession(ctx, broadcastListener, Presets.Configuration.STANDARD_LANDSCAPE, Presets.Devices.BACK_CAMERA(ctx));
์คํธ๋ฆฌ๋ฐ์ ํธ๋ํฐ์ ์ ๋ฉด ์นด๋ฉ๋ผ๋ฅผ ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด ํ๋จ์ ์ฝ๋๋ก ์ถ๊ฐํด ์ฃผ๋ฉด ๋๋ค!
Context ctx = getApplicationContext();
BroadcastSessionbroadcastSession = new BroadcastSession(ctx, broadcastListener, Presets.Configuration.STANDARD_PORTRAIT, Presets.Devices.FRONT_CAMERA(ctx));
์นด๋ฉ๋ผ๋ฅผ ๋ฑ ์ผฐ์ ๋ ๋ ์ฆ๋ก ๋ณด์ด๋ ํ๋ฉด์ด ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ก ์ ๊ณต๋๋ ๊ฒ์ฒ๋ผ ์ด๋ค ํ๋ฉด์ด ๋ณด์ฌ์ง๋์ง ํ์ธํ๊ธฐ ์ํด xml ํ์ผ์ LinearLayout์ผ๋ก ๋ฏธ๋ฆฌ๋ณด๊ธฐ ๋ ์ด์์์ ์ถ๊ฐํ๊ณ , MainActivity.java ํ์ผ์๋ ํ๋จ์ ์ฝ๋๋ฅผ ์ถ๊ฐํด ์ค๋ค.
broadcastSession.awaitDeviceChanges(() -> {
for(Device device: session.listAttachedDevices()) {
if(device.getDescriptor().type == Device.Descriptor.DeviceType.CAMERA) {
LinearLayout previewHolder = findViewById(R.id.previewHolder);
ImagePreviewView preview = ((ImageDevice)device).getPreviewView();
preview.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT));
previewHolder.addView(preview);
}
}
});
LinearLayout previewHolder = findViewById(R.id.previewHolder);
๊ฐ๋จํ๊ฒ ์ฝ๋ ํ ์ค๋ก ์คํธ๋ฆฌ๋ฐ์ ์์ํ ์ ์๋ค!
URL ๋ถ๋ถ์๋ IVS ์ฑ๋์ ์์ง ์๋ฒ, STREAMKEY ๋ถ๋ถ์๋ IVS ์ฑ๋์ ์คํธ๋ฆผ ํค ์ ๋ณด๋ฅผ ๋ฐ์์ ์
๋ ฅํ๋ฉด ๋๋ค.
broadcastSession.start(IVS_RTMPS_URL, IVS_STREAMKEY);
๋ฐฉ์ก ์์ ๋ฒํผ์ ํตํด ๋ฒํผ์ ๋๋ฆ์ผ๋ก์จ ์คํธ๋ฆฌ๋ฐ์ด ์์๋๋๋ก ํ๊ณ ์ถ๋ค๋ฉด, ํ์๊ฐ ๊ตฌํํ ๊ฒ์ฒ๋ผ OnClickListener() ํจ์๋ฅผ ํตํด ์ค์ ํด ์ฃผ๋ฉด ๋๊ฒ ๋ค. ์ถ๊ฐ๋ก ๋ฒํผ์ ๋๋ฅด๋ฉด ๊ฐ๋จํ Toast message๊ฐ ํจ๊ป ์ถ๋ ฅ๋๋๋ก ํ์๋ค.
Button broadbutton = (Button)findViewById(R.id.startbroad);
broadbutton.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
broadcastSession.start("rtmps://3c90cab980bd.global-contribute.live-video.net:443/app/", "sk_ap-northeast-2_yFcoiZCkIOLg_vKCoVZPK8UBYWahI8dUXOVUmQlwASj");
Toast.makeText(ctx,"์ดฌ์์ ์์ํฉ๋๋ค", Toast.LENGTH_SHORT).show();
Toast.makeText(ctx,"๋คํธ์ํฌ์ ์ ์ ์ฐ๊ฒฐ์ ์ ์งํด ์ฃผ์ธ์", Toast.LENGTH_SHORT).show();
}
});
์ด์ ๊ณผ์ ๊ณผ ๋์ผํ๋ค. ์ค๋ช ์ ์ค์ด๋๋ก ํ๊ฒ ๋ค. ์ฝ๋๋ฅผ ์ฐธ๊ณ ํ์.
broadcastSession.stop();
๋ง์ฐฌ๊ฐ์ง๋ก ๋ฒํผ์ ํตํด ๋์ํ๋๋ก ํ๊ณ ์ถ๋ค๋ฉด
Button stopbutton = (Button)findViewById(R.id.stopbroad);
stopbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
broadcastSession.stop();
Toast.makeText(ctx,"์ดฌ์์ ์ข
๋ฃํฉ๋๋ค", Toast.LENGTH_SHORT).show();
}
});
๋ธ๋ก๋์บ์คํธ ์ธ์ ์ด ๋ ์ด์ ์ฌ์ฉ๋์ง ์๋ ๊ฒฝ์ฐ, ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ฌ์ฉํ๋ ๋ฆฌ์์ค๋ฅผ ํด์ ํด ์ฃผ์ด์ผ ํ๋ค. ํ๋จ์ ์ฝ๋๋ฅผ MainActivity.java ํ์ผ์ ์ถ๊ฐํด ์ฃผ์.
@Override
protected void onDestroy() {
super.onDestroy();
previewHolder.removeAllViews();
broadcastSession.release();
}
Android Studio ๋ด์ ์๋ฎฌ๋ ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌ ์คํธ๋ฆฌ๋ฐ์ ์์ํ๊ณ , AWS IVS ์๋น์ค ์ฝ์ ๋ด์ ๋ด ์ฑ๋์์ ํด๋น ์คํธ๋ฆฌ๋ฐ์ด ์ํํ๊ฒ ์งํ๋จ์ ํ์ธํ ์ ์์๋ค.
๋ณธ ๊ฒ์๊ธ์์์ ์ค๋ช ์ ์ฌ๊ธฐ๊น์ง์ด๋ค.
์์์๋ ์ธ๊ธํ์ง๋ง, AWS์์๋ ๊ณต์์ ์ผ๋ก SDK ์ฌ์ฉ์ ๋ํ ๊ฐ์ด๋ ๋ฐ demo app ์ฝ๋๋ฅผ ์ ๊ณตํ๋ ๊ด๋ จ ๋ด์ฉ์ด ๊ถ๊ธํ๋ค๋ฉด ํ์ดํผ๋งํฌ๋ฅผ ํตํด ์ดํด๋ณด๋ฉด ๋๊ฒ ๋ค.
Hi, where do you place the BroadcastSession var? Is it on oncreate or onstart? If you could upload the whole project l it would be great