def clkMakeMov(self, widget, event, data=None): if 0 == self.countPublish(): self.Alert("Publish가 안된 샷이 있습니다. Publish 된 정보를 기준으로 MOV 생성작업을 하게 됩니다.") return False stereo_type = {"l" : "_left", "r" : "_right"} for list_row in ListStore.projShotStore: row_selected = list_row[const.COLUMN_CHOICE] if not row_selected: continue db_shot_record = self.datastore.getShotFromName(list_row[const.COLUMN_SHOTLIST]).first() original_width = int(db_shot_record.width) original_height = int(db_shot_record.height) half_width = original_width / 2 half_height = original_height / 2 thumbnail_width = 300 thumbnail_height = int(float(original_height) / float(original_width) * thumbnail_width) new_shot_name = util.NewShotNameDict() new_shot_name["SEQ"] = "%s_" % db_shot_record.seq new_shot_name["SHOT_NUMBER"] = "%s_" % db_shot_record.shotnumber new_shot_name["TYPE"] = "plate_%s_" % db_shot_record.type new_shot_name["WIDTH"] = "%dx" % original_width new_shot_name["HEIGHT"] = "%d" % original_height new_shot_name["STEREO"] = "%s" % stereo_type.get(db_shot_record.isstereo, '') # New Shot Name if db_shot_record.type == "org": # (박성진 코디네이터 요청. 2012/02/20) del new_shot_name["TYPE"] newShotName = "".join(new_shot_name.values()) if "myWay" == const.PROJECT: del new_shot_name["SEQ"] newShotName = "".join(new_shot_name.values()) TypeDirectory = split(db_shot_record.publishpath)[0] ResolutionHalfDir = path_join(TypeDirectory, "%dx%d" % (half_width, half_height)) ThumbnailDir = path_join(TypeDirectory, "thumbnail") tmp_mov_directory = path_join(TypeDirectory, ".%.2f" % time.time()) if not exists(tmp_mov_directory): makedirs(tmp_mov_directory) JpegNuke = path_join(tmp_mov_directory, "%s_jpeg.nk" % newShotName) MovNuke = path_join(tmp_mov_directory, "%s_mov.nk" % newShotName) newFrameInfo = util.getNewFrame(db_shot_record.publishpath) dpx_files = glob("%s/%s.[0-9]*%s" % (db_shot_record.publishpath, newShotName, db_shot_record.fileformat)) dpx_files.sort() middle_frame = len(dpx_files) / 2 Thumbnail_FileName = "%s.jpg" % splitext(basename(dpx_files[middle_frame]))[0] thumb_fd = open(const.watch_thumb_file, "a") thumb_fd.write("%s\t%s\t%s\t%s\n" % (thumbnail_width, thumbnail_height, dpx_files[middle_frame], path_join(ThumbnailDir, Thumbnail_FileName))) thumb_fd.close() time.sleep(1) movie_src_ext = splitext(dpx_files[0])[1] # Mov Image nuke_helper.nuke_run( path_join(db_shot_record.publishpath, "%s.%%04d%s" % (newShotName, movie_src_ext)), db_shot_record.clipname, newShotName, 1024, 720, '%d-%d' % (newFrameInfo["START"], newFrameInfo["END"]), path_join(tmp_mov_directory, "%s.%%04d.jpg" % newShotName), JpegNuke, path_join("/local", "%s.mov" % newShotName), True, MovNuke ) # Mov Alfred MovAlfred = tractor_script.tractorSubmission( ( '<ScanDataTransfer> ReMOV - %s' % newShotName, newFrameInfo["START"], newFrameInfo["END"], JpegNuke, '/bin/mv %s %s' % ( path_join("/local", "%s.mov" % newShotName), path_join(TypeDirectory, "%s.mov" % newShotName) ), MovNuke, tmp_mov_directory, path_join(TypeDirectory, "._%s.mov" % newShotName) ), True) open(path_join(tmp_mov_directory, "%s.alf" % newShotName), "w").write(MovAlfred) # AlfredRunning tractor_script.tractor_running(path_join(tmp_mov_directory, "%s.alf" % newShotName)) self.Alert(u"MOV를 만들어달라고 Tractor에 요구했습니다.")
def clkPublish(self, widget, event, data=None): tmp_path = path_join(const.SCAN_ROOT, "tmp") # tmp_path exists if not exists(tmp_path): makedirs(tmp_path) # 물론 projectShot에서 체크된 된것만 수행한다) for row in ListStore.projShotStore: if not row[const.COLUMN_CHOICE]: continue # Choice가 선택되어진 경우만 수행한다. # Publish 단계에선 DB정보가 완성되어 있다(ScanInfo.py에서 이미 데이터를 넣는다) ################################################################ # shotname을 기준으로 데이터베이스에 질의해서 db_shot_record에 값을 담는다. ################################################################ db_shot_record = self.datastore.getShotFromName(row[const.COLUMN_SHOTLIST]).first() if db_shot_record == None: # 데이터가 없음을 알리고 루프를 반복한다. 물론 그럴리는 없겠지만... # 별도의 처리를 하기 전까지는 그냥 루프만 반복한다. continue # 새로운 Seq Name이나 새 Seq Number가 없으면 작업 하나 마나다. 에러 메시지 출력해주게 한다.(미정) if (None == db_shot_record.seq) or (None == db_shot_record.shotnumber): return False tmp_shot_directory = path_join(tmp_path, db_shot_record.shotname) # Dpx Size ShotMaxWidth = int(db_shot_record.width) ShotMaxHeight = int(db_shot_record.height) # Thumbnail은 항상 300으로 고정한다. thumbnail_width = 300 thumbnail_height = int(float(ShotMaxHeight) / float(ShotMaxWidth) * thumbnail_width) # Half Size half_width = ShotMaxWidth / 2 half_height = ShotMaxHeight / 2 tmp_resolution_dir = path_join(tmp_shot_directory, "%dx%d" % (ShotMaxWidth, ShotMaxHeight)) if not exists(tmp_resolution_dir): makedirs(tmp_resolution_dir) # dpx, tga, cin 등의 파일을 resolution_dir에 복사 dpx_files = glob("%s/%s/*" % (const.SCAN_ROOT, db_shot_record.shotname)) # 임시 디렉터리에 파일이 존재하면 복사하지 않게 한다. new_resolution_files = glob("%s/*" % tmp_resolution_dir) # 이미 수행되어 있는 경우 다시 복사하지 않게 한다.(퍼블리시 여부로 대체한다.) if len(dpx_files) == len(new_resolution_files): # 하나라도 값이 다르면 수행하지 않게 한다. self.Alert(u"디렉터리 %s는 이미 임시 파일이 있습니다. tmp 디렉터리를 먼저 삭제하셔야 합니다" % db_shot_record.shotname) continue #return False util.fileCopy(dpx_files, tmp_resolution_dir) # 임시 디렉터리로 복사가 완료되었으면 이름을 변경후 Nuke를 사용하여 # 썸네일 및 MOV파일을 만들어넣고 seq 폴더로 데이터를 옮긴다. if 0 == len(db_shot_record.type.strip()): # Type이 비어있는 값이면... util.changesetRecord(db_shot_record, "type", "org") newShotStereo = db_shot_record.isstereo.strip().lower() publish_dir = path_join("/", "show", const.PROJECT, "seq") # Seq, SeqNumDir, TypeDirectory, ResolutionDir, ResolutionHalfDir, ThumbnailDir SeqDir = path_join(publish_dir, db_shot_record.seq) SeqNumDir = path_join(SeqDir, "%s_%s" % (db_shot_record.seq, db_shot_record.shotnumber)) # Rule : 김희경_110804_Rule if "myWay" == const.PROJECT: SeqNumDir = path_join(SeqDir, db_shot_record.shotnumber) TypeDirectory = path_join(SeqNumDir, "plate", db_shot_record.type) # Resolution Dir Create ResolutionDir = path_join(TypeDirectory, "%dx%d" % (ShotMaxWidth, ShotMaxHeight)) ResolutionHalfDir = path_join(TypeDirectory, "%dx%d" % (ShotMaxWidth / 2, ShotMaxHeight / 2)) ThumbnailDir = path_join(TypeDirectory, "thumbnail") # 비어있는 디렉터리가 있으면 생성시킨다. for item in (SeqDir, SeqNumDir, TypeDirectory, ResolutionDir, ResolutionHalfDir, ThumbnailDir): if not exists(item): makedirs(item) ################################################################ # File Renaming Rules Define # # (선결조건 : 이름이 먼저 변경되어 있어야 함)여기에서 우선 tmp/샷네임 # 디렉터리 안에서 이름을 교체하고 썸네일과 하프 사이즈를 생성할 수 있는 # .nk, .alf 파일을 각각 만들고 os.system 메소드로 실행한다. ################################################################ stereo_type = {"l" : "_left", "r" : "_right"} dpx_files = glob("%s/*" % tmp_resolution_dir) dpx_files.sort() # 정상적인 썸네일 및 영상 파일을 만들기 위해서... start_frame_number = 101 movie_src_rename_files = dict() for dpx_item in dpx_files: movie_src_file_ext = splitext(dpx_item) # 다양한 영상 소스에 대한 대응을 하기 위해서임 # New Fille Name Dictionaries new_file_name = util.NewShotNameDict() new_file_name["SEQ"] = "%s_" % db_shot_record.seq new_file_name["SHOT_NUMBER"] = "%s_" % db_shot_record.shotnumber new_file_name["TYPE"] = "plate_%s_" % db_shot_record.type new_file_name["WIDTH"] = "%dx" % ShotMaxWidth new_file_name["HEIGHT"] = "%d" % ShotMaxHeight new_file_name["STEREO"] = "%s." % stereo_type.get(db_shot_record.isstereo, '') new_file_name["FRAME"] = "%s." % str(start_frame_number).zfill(4) new_file_name["EXT"] = "%s" % movie_src_file_ext[1][1:] # 샷 타입이 org인 경우 _plate_org를 파일 이름과 스파르타 등록네임에서 빼달라는 박성진 코디 요청 있었음 # 메일을 받았을 당시 참조 메일 없었으니 이것으로 생기는 혼선에 대해선 박성진 코디네이터에게 책임이 있음 # 2012.2.20 19:32 이상호([email protected]) if db_shot_record.type == "org": del new_file_name["TYPE"] new_file_name = "".join(new_file_name.values()) # Myway Rule # Rule Name : 김희경_110804_Rule if "myWay" == const.PROJECT: del new_file_name["SEQ"] new_file_name = "".join(new_file_name.values()) # 영상 소스 파일 이름 변경 util.fileRename(dpx_item, path_join(tmp_resolution_dir, new_file_name)) start_frame_number += 1 del new_file_name # Thumbnail 파일 생성을 위해서 tmp_resolution_dir의 내용을 리스트로 담아두고 썸네일을 생성할 때 # 사용하게 한다.(디렉토리 경로는 미리 변경해두어야 한다.) dpx_files = glob("%s/*" % tmp_resolution_dir) dpx_files.sort() # 정상적인 썸네일 및 영상 파일을 만들기 위해서... ################################################################ # 이제 파일을 복사한다. ################################################################ new_shot_name = util.NewShotNameDict() new_shot_name["SEQ"] = "%s_" % db_shot_record.seq new_shot_name["SHOT_NUMBER"] = "%s_" % db_shot_record.shotnumber new_shot_name["TYPE"] = "plate_%s_" % db_shot_record.type new_shot_name["WIDTH"] = "%dx" % int(db_shot_record.width) new_shot_name["HEIGHT"] = "%d" % int(db_shot_record.height) new_shot_name["STEREO"] = "%s" % stereo_type.get(db_shot_record.isstereo, '') # New Shot Name # 마이웨이 프로젝트인 경우 newShotName도 형식이 달라져야 한다. # Rule Name : 김희경_110804_Rule if db_shot_record.type == "org": # (박성진 코디네이터 요청. 2012/02/20) del new_shot_name["TYPE"] # 기본 모드 newShotName = "".join(new_shot_name.values()) if "myWay" == const.PROJECT: del new_shot_name["SEQ"] newShotName = "".join(new_shot_name.values()) util.tmpPathToDestPath.tmp_path = tmp_shot_directory util.tmpPathToDestPath.dst_path = TypeDirectory # 디렉터리 경로를 임시 변환하게 하기 위하여 map을 호출하여 임시 경로를 새 경로로 # 변경하게 한다. dpx_files = map(util.tmpPathToDestPath, dpx_files) middle_frame = len(dpx_files) / 2 # Thumbnail File Name(Half, Thumbnail) Thumbnail_FileName = "%s.jpg" % splitext(basename(dpx_files[middle_frame]))[0] newFrameInfo = util.getNewFrame(tmp_resolution_dir) if exists(tmp_shot_directory): # 이동할 리스트를 생성한다. copy_list = glob("%s/*/*" % tmp_shot_directory) # 실제 파일을 move 시킨다. util.fileMove(copy_list, TypeDirectory) self.writePublishInfo( path_join(TypeDirectory, "%s.mov" % newShotName), path_join(ThumbnailDir, Thumbnail_FileName), ResolutionDir, newFrameInfo, db_shot_record ) # DB에도 정보가 기록이 완료되면 tmp 디렉터리도 삭제한다. rmtree(tmp_shot_directory) ################################################################ # 썸네일과 MOV 생성(MOV는 Nuke Run) ################################################################ # nuke, alfredo 스크립트 파일과 임시 MOV를 생성하게 위한 디렉터리를 생성한다. # alf, nk 파일 보관용 tmp_mov_directory = path_join(TypeDirectory, ".%.2f" % time.time()) if not exists(tmp_mov_directory): makedirs(tmp_mov_directory) # Half Image, Thumbnail Image # (스테레오 샷은 스파르타 업로드 시 걸러지므로 여기에선 스테레오 여부를 무시하고 썸네일을 생성하게 한다) JpegNuke = path_join(tmp_mov_directory, "%s_jpeg.nk" % newShotName) MovNuke = path_join(tmp_mov_directory, "%s_mov.nk" % newShotName) thumb_fd = open(const.watch_thumb_file, "a") thumb_fd.write("%s\t%s\t%s\t%s\n" % (thumbnail_width, thumbnail_height, dpx_files[middle_frame], path_join(ThumbnailDir, Thumbnail_FileName))) thumb_fd.close() time.sleep(1) # 영상 소스의 확장자 얻어오기 movie_src_ext = splitext(dpx_files[0])[1] # [MOV] 생성하기(Jpeg 생성, MOV 생성) nuke_helper.nuke_run( path_join(ResolutionDir, "%s.%%04d%s" % (newShotName, movie_src_ext)), db_shot_record.clipname, newShotName, 1024, # 확인용 720, # 확인용 '%d-%d' % (newFrameInfo["START"], newFrameInfo["END"]), path_join(tmp_mov_directory, "%s.%%04d.jpg" % newShotName), JpegNuke, path_join("/local", "%s.mov" % newShotName), True, MovNuke ) MovAlfred = tractor_script.tractorSubmission( ( '<ScanDataTransfer> MOV - %s' % newShotName, newFrameInfo["START"], newFrameInfo["END"], JpegNuke, '/bin/mv %s %s' % ( path_join("/local", "%s.mov" % newShotName), path_join(TypeDirectory, "%s.mov" % newShotName) ), MovNuke, tmp_mov_directory, path_join(TypeDirectory, "._%s.mov" % newShotName) ), True) open(path_join(tmp_mov_directory, "%s.alf" % newShotName), "w").write(MovAlfred) # AlfredRunning tractor_script.tractor_running(path_join(tmp_mov_directory, "%s.alf" % newShotName)) self.datastore.shotSave(db_shot_record) gui_util.updateProjectShots(self.datastore) self.Alert("Publish가 모두 완료되었습니다.")