2013-11-20 8 views
1

내 웹캠/스마트 폰에서 비디오 피드를 가져와 실행 중에 보여주는 처리 중이 스케치에서 작업 중입니다. tt 자막 파일로 변환 된 .srt 파일을 영화에서 가져 오려고합니다. 텍스트 파일에는 실제 텍스트 앞에 시작 및 끝 부제 프레임을 나타내는 모든 숫자가 있음을 알 수 있습니다. 내가하고 싶은 무엇처리에서 자막 가져 오기

{9232}{9331}Those swings are dangerous.|Stay off there. I haven't fixed them yet. 
{9333}{9374}I think you're gonna live. 

가 시작/끝 프레임 오른쪽에 실행으로

  1. 이 번호를 사용하고 설정하는 코드를 OUTA 파악하는 것입니다 : 여기

    은 예입니다 시간은 영화에서와 마찬가지로
  2. 자막 표시
  3. '|'기호를 스크립트에서 줄 바꾸기를 나타내는 기호로 사용하는 방법을 알아보십시오.

나는

내가 무엇을 내가 원하는 것은 전체

일에서 나를 구원 것 같아요 .. 즉 이미 상당히 복잡 할 수도 있지만 난 그냥 누군가가 과거에 비슷한 아무 짓 여부를 확인하고 싶어서 생각 각 자막
if ((current_frame > 9232) && ((current_frame < 9331)) { 
    text("Those swings are dangerous.", 200, 500/2); 
    text("Stay off there. I haven't fixed them yet..", 200, (500/2 + 35)); 
} 

일이 ...

나는 '만약'그 '에 대한'에서 떨어져 많은 명령을 잘 처리에 아주 새로운 그래서 아니다, 파일과 무지한을 .txt 인 수입에서 초보자 ~ 안에 배열로 orking하기. 하지만 난 정말 마지막 두 비트에 좋은 방법을 찾고 싶어요 ..

을 어떤 형태로 어떤 도움이 크게 감사합니다 :)

건배, 조지

답변

2

을 적절한 자막 표시의 경우 (텍스트의 벽을 사전에 죄송 아래 설명) 다음과 같은 일을 할 수있는 :

String[] subtitles = loadStrings("subtitles.txt"); 
int currentFrame = 0; 
int subtitleIndex = -1; 
int startFrame = -1, endFrame = -1; 
int fontSize = 10; //change to suit your taste 
String[] currentSubtitle; 
... 

//draw loop start: 
//video drawing code goes here 

if(currentFrame > endFrame){ //update which subtitle is now/next 
    subtitleIndex++; 
    startFrame = int(subtitles[subtitleIndex].split("\\}\\{")[0].substring(1)); 
    endFrame = int(subtitles[subtitleIndex].split("\\}\\{")[1].split("\\}")[0]); 
    currentSubtitle = subtitles[subtitleIndex].split("\\}")[2].split("\\|"); 
} 
if(currentFrame >= startFrame && currentFrame <= endFrame){ 
    for(int i = 0; i < currentSubtitle.length; i++){ 
    text(currentSubtitle[i], width/2, height - fontSize * (currentSubtitle.length - i)); 
    } 
} 
currentFrame++; 
//draw loop end 

것은 아마 그, 그래서 여기에 당신에게 꽤 협박 보이는 일부 워크를 통해 해설입니다. 프로그램 유형은 state machine입니다. 자막을 표시하는 상태인지 여부입니다. 나중에 코드를 디자인 할 때이를 염두에 두겠습니다. 먼저 변수를 선언하고 초기화해야합니다.

첫 번째 줄은 loadStrings() 함수를 사용하며이 함수는 텍스트 파일을 읽고 String 배열을 반환합니다. 배열의 각 요소는 파일의 한 줄입니다. 물론 파일에 맞게 파일 이름을 변경해야합니다.

코드에서 current_frame이라는 변수를 사용합니다.이 코드는 매우 좋은 아이디어이지만 자바 코딩 규칙에 맞게 currentFrame으로 이름을 변경했습니다. 0부터 시작하고, 나중에 코드가 모든 프레임 디스플레이에서 증가합니다. 이 변수는 자막 시퀀스에있는 위치와 표시 할 메시지 (있는 경우)를 알려줍니다.

각 자막이 시작하고 끝나는 프레임의 정보가 문자열로 인코딩되기 때문에이를 코드에 통합하는 것은 약간 까다 롭습니다. 지금은 "현재"자막 - 현재 표시 중이거나 다음에 표시 될 자막 - 시작 및 종료 시점을 나타내는 변수를 만들어 보겠습니다.또한 subtitles 배열의 어떤 요소가 "현재"자막인지를 추적하는 색인을 생성합니다. 이 변수는 모두 -1에서 시작하며 약간 이상하게 보일 수 있습니다. currentFrame0으로 초기화했지만, 실제로는 "초기"값이 아닙니다. 0을 선택한 경우 첫 번째 부제가 프레임 0에서 시작되고 끝나지 않을 수 있고 다른 양수가 많은 의미가 없으므로 사실이 아닙니다. -1은 종종 변수가 실제로 사용되기 전에 대체 될 더미 인덱스로 사용되기 때문에 여기서도이를 수행 할 것입니다.

이제 최종 변수는 currentSubtitle입니다. 즉각적인 생각은이 배열을 String 배열이 아닌 보통 String이어야한다는 것입니다. 그러나 각 자막은 파이프 (|) 기호로 분할해야 할 수도 있으므로 각 자막은 실제로 여러 줄의 텍스트를 나타낼 수 있으므로 안전을 위해 배열을 만듭니다. 일부 자막은 단일 요소 배열 일 수도 있지만 괜찮습니다.

이제 어려운 부분을 위해!

아마도 코드가 (조건이 충족 될 경우) 각 반복에서 해당 비디오 프레임이 화면에 그려되고 그 루프의 일종을해야합니다, 자막은 그것의 맨 위에 그려집니다. 나는 당신의 질문의 일부가 아니므로 비디오 부분을 생략했습니다.

우리는 뭔가를하기 전에 변수의 일부가 아직 실제 값을 가지고 있지 않다는 것을 기억해야합니다. 전에 나온 -1의 값을 설정해야합니다. 드로잉 루프의 기본 논리는 1) 자막을 그릴 필요가 있는지 파악한 후 그려야하며, 2) "현재"자막을 배열의 다음 자막으로 이동해야하는지 파악합니다. 루프를 통해 처음으로 아직 그것에 대해 아무것도 모르기 때문에 # 2 먼저 해봅시다! 다음 자막으로 이동하기위한 기준 (일반적으로)은 현재 제목의 끝까지 지나친 것입니다 : currentFrame > endFrame. 그것이 사실이라면 우리는 모든 변수를 다음 부제로 옮겨야합니다. subtitleIndex은 쉽습니다. 우리는 하나를 추가하고 완료했습니다. 나머지는 쉽지 않습니다. 나는 그것이 역 겨 운다는 것을 안다. 그러나 나는 흐름을 깨지 않기 위해 끝 부분에서 이야기 할 것이다. 그냥 기다릴 수없는 경우 아래쪽으로 건너 뜁니다.

(필요한 경우) 모든 변수를 현재 자막과 관련되도록 변경 한 후에는 실제 표시해야합니다. 두 번째 if 문은 현재 자막의 프레임 경계 안에 "있는지"여부를 확인합니다. currentSubtitle 변수는 지금 바로 표시되어야하는 자막을 참조 할 수 있거나 시퀀스의 다음 자막 만 참조 할 수 있으므로이 프레임에 대해 어느 것이 적합한 지 확인하기 위해 몇 가지 검사를 수행해야합니다. 그것은 두 번째입니다. if 성명서 - 우리가 시작을 지나서 끝나기 전에 부제를 표시해야합니다! 우리의 currentSubtitle 변수는 배열이므로, 직접 표시 할 수는 없습니다. 우리는 그것을 반복하고 각 요소를 별도의 줄에 표시해야합니다. text() 명령에 대해 언급 했으므로 여기서는 깊이 들어가지 않을 것입니다. 까다로운 비트는 여러 행에 있어야하기 때문에 텍스트의 y 좌표입니다. 첫 번째 요소가 두 번째 요소보다 위에 있고 세 번째 요소 위에 있어야합니다. 이렇게하려면 y 좌표는 우리가 어느 요소에 있는지에 따라 달라지며, i으로 표시됩니다. fontSize의 값을 변경하여 행간의 차이를 조정할 수 있습니다. 그게 당신의 취향에 달려 있습니다. 당신이 설정 한 숫자가 픽셀 단위의 선 높이와 동일하다는 것을 알아라.

위의 설명을 원하지 않는 지저분한 비트가 있습니다. 이 코드는 Stringsplit() 메서드에 따라 달라지며 분할하려는 문자열에 대해 수행되며 문자열을 분할하는 방법 (regex)을 나타내는 매개 변수로 문자열을 사용합니다.파일의 자막 줄에서 startFrame을 가져 오려면 중괄호를 통해 분할해야합니다. 그 이유는 숫자 사이의 구분선이기 때문입니다. 첫째, 우리는 "} {"이 발생하는 모든 곳에서 첫 번째 숫자 바로 다음 (그리고 두 번째 바로 전에) 문자열을 분할합니다. split()은 배열을 반환하기 때문에 대괄호 사이의 인덱스를 사용하여 배열에서 하나의 문자열을 참조 할 수 있습니다. 첫 번째 숫자는 "} {"로 분할하여 첫 번째 문자열 반환에 포함되므로 색인 0을 사용합니다. split()은 분리하려는 것을 제거하기 때문에 (예를 들어) "{1234"를 반환합니다. 이제 첫 번째 문자 다음에 오는 substring을 가져와 int()을 사용하여 int로 변환해야합니다. 이제 끝났습니다!

두 번째 숫자는 비슷한 방법을 사용할 수 있습니다. "} {"로 다시 나눠서, 이번에는 반환 된 배열에서 두 번째 (인덱스 1) 요소 만 가져옵니다. 자, 우리는 "9331} 그 스윙은 댕글입니다 ...", 다시 으로 나눠서 배열의 첫 번째 문자열을 선택하고 int로 변환하면 끝났습니다! 두 경우 모두 우리는 처음에 loadStrings()을 사용하여로드 한 파일의 원시 입력을 나타내는 원래 문자열로 subtitles[subtitleIndex]을 사용하고 있습니다. 이 모든 분할 중에 subtitles의 원래 문자열은 변경되지 않습니다. split(), substring() 등은 새 시퀀스 만 반환하고 호출 한 문자열은 수정하지 않습니다.

당신은 split() 전화를 어지럽히고 백 슬래시의 무리가있는 것을 볼 수 있습니다, 그 순서의 마지막 줄 :

마지막으로 어떻게 작동하는지 알아 내기 위해 당신에게 그것을 떠날거야. split()은 간단한 문자열이 아닌 정규식을 사용하기 때문입니다. 정규 표현식은 여기에 들어 가지 않는 많은 특수 표기법을 사용하지만, "}{"과 같은 것으로 split()을 전달한 경우에는 정규 표현식을 해석하려고 시도하며 예상대로 동작하지 않습니다. 문자가 escape이고 문자가 split() 일 때 특수 문자로 해석되지 않도록하고 문자 자체를 원한다고 말하면됩니다. 그렇게하기 위해, 이스케이프해야하는 문자 앞에 백래시를 사용합니다. 그러나 백 슬래시 자체는 또 다른 특수 문자이므로 이스케이프 처리해야합니다. 이 결과는 "\\{"과 같습니다. 첫 번째 백 슬래시는 세 번째 문자가 무엇이든간에 이스케이프 처리되는 두 번째 이스케이프 문자를 이스케이프합니다. | 문자도 이스케이프 처리해야합니다.

죄송 텍스트의 벽! 지능적이고 정중하게 질문 된 질문을 보는 것이 좋으므로 좋은 답을 줄 것이라고 생각했습니다.

+0

환상적인 답변! – mdomino