사소한 아이의 소소한 행복

연예인들이 내는 책이 더 이상 새롭지 않은 시대다. 하지만 출간하자마자(그것도 하루키의 <1Q84>를 제치고) 당당히 베스트셀러에 입성해 독자들의 울림을 끌어내는 건 마지막 마침표 하나까지 직접 고치고 또 고치며 이 책에 올인한 최강희란 배우의 진정성일 것이다.

프로필 by ELLE 2009.11.05

1 <사소한 아이의 소소한 행복> 최강희 지음, 북노마드
2 <게으른 즐거움> 댄 키란, 홈 호지킨슨 엮음, 이레
`); if(getCookie("expend")){ $(".tooltip_div").remove(); } $(".close_btn").on("click",function(){ setCookie("expend", "true", 1); $(".tooltip_div").remove(); }); } }); if(!isRequiredAuth || authUserIdx === -1){ window.addEventListener('message', getLoginBtn); } $(".btn_ico.tts").on("click", function () { //로그인 체크 추가 if(authUserIdx === -1){ $("#loginLayer").show(); return false; } if (audio.readyState === 0) { $('#loading').show(); chkTTSFile = true; console.log("오디오가 로드되지 않음."); return false; } //음성 파일이 생성된 경우 let audPause = document.getElementById("audio").paused; if($("#audio").attr("src") != ""){ console.log("TTS 파일명 : " + $("#audio").attr("src")); if(audPause){ playAudio(); }else{ document.getElementById("audio").pause(); } }else{ setTimeout(() => { ttsApi(true); }, "1000"); } }); }); //재생 상태관리 audio.onplay = () => { console.log("오디오 재생 시작!"); chkTTSFile = false; $('.btn_ico.tts').removeClass("off").addClass("on"); $(".btn_ico.tts").removeClass("pause"); } audio.onpause = () => { console.log("오디오 일시 정지됨."); $('.btn_ico.tts').removeClass("on").addClass("pause"); $(".btn_ico.tts").removeClass("off"); } audio.onended = () => { console.log("오디오 재생 완료!"); $('.btn_ico.tts').removeClass("on").addClass("off"); $(".btn_ico.tts").removeClass("pause"); } audio.onloadeddata = () => { if(chkTTSFile){ $('#loading').hide(); playAudio(); } } function getLoginBtn(){ setTimeout(()=>{ if(isRequiredAuth && authUserIdx !== -1){ ttsApi(false); } },1000); } function ttsApi(isShow) { var resdata = { //'text': bodyText, 'articleId': articleId }; if (!isTTSLoad) { console.log("ttsAPI 호출"); isTTSLoad = true; $.ajax({ type: "post", url: "/ttsapi/convert-to-speech", dataType: "json", data: JSON.stringify(resdata), processData: false, contentType: "application/json;charset=UTF-8", //async: false, success: function (response) { if (response.code == 400) { console.log(response.error_msg); console.log(response.gac); return; } if (response.audio_file_url) { $("#audio").attr("src", response.audio_file_url); } else { let audioBlob = base64ToBlob(response.audio_byte, "mp3"); $("#audio").attr("src", window.URL.createObjectURL(audioBlob)); } if (isShow) { playAudio(); $('#loading').hide(); } }, error: function () { isTTSLoad = false; } }); } } function playAudio() { document.getElementById("audio").play().catch(error => { console.error("오디오 재생 오류:", error); }); } function base64ToBlob(base64, fileType) { let typeHeader = "data:application/" + fileType + ";base64,"; // base64 헤더 파일 유형 정의 let audioSrc = typeHeader + base64; let arr = audioSrc.split(","); let array = arr[0].match(/:(.*?);/); let mime = (array && array.length > 1 ? array[1] : type) || type; // url헤더 제거하고 btye로 변환 let bytes = window.atob(arr[1]); // 예외를 처리하고 0보다 작은 ASCII 코드를 0보다 큰 값으로 변환 let ab = new ArrayBuffer(bytes.length); // 뷰 생성(메모리에 직접): 8비트 부호 없는 정수, 길이 1바이트 let ia = new Uint8Array(ab); for (let i = 0; i < bytes.length; i++) { ia[i] = bytes.charCodeAt(i); } return new Blob([ab], { type: mime }); }