def verify(self, progress=None): """verifies the current file for correctness returns True if the file is okay raises an InvalidFile with an error message if there is some problem with the file""" # Checking for a truncated Ogg stream typically involves # verifying that the "end of stream" flag is set on the last # Ogg page in the stream in the event that one or more whole # pages is lost. But since the OpusFile decoder doesn't perform # this check and doesn't provide any access to its internal # Ogg decoder (unlike Vorbis), we'll perform that check externally. # # And since it's a fast check, we won't bother to update progress. from audiotools.ogg import PageReader import os.path try: reader = PageReader(open(self.filename, "rb")) except IOError as err: raise InvalidOpus(str(err)) try: page = reader.read() while (not page.stream_end): page = reader.read() reader.close() except (IOError, ValueError) as err: raise InvalidOpus(str(err)) return AudioFile.verify(self, progress)
def get_metadata(self): """returns a MetaData object, or None raises IOError if unable to read the file""" from cStringIO import StringIO from audiotools.bitstream import BitstreamReader from audiotools.ogg import PacketReader, PageReader from audiotools.vorbiscomment import VorbisComment reader = PacketReader(PageReader(open(self.filename, "rb"))) identification = reader.read_packet() comment = BitstreamReader(StringIO(reader.read_packet()), True) (packet_type, packet_header) = comment.parse("8u 6b") if ((packet_type == 3) and (packet_header == 'vorbis')): vendor_string = \ comment.read_bytes(comment.read(32)).decode('utf-8') comment_strings = [ comment.read_bytes(comment.read(32)).decode('utf-8') for i in xrange(comment.read(32))] if (comment.read(1) == 1): # framing bit return VorbisComment(comment_strings, vendor_string) else: return None else: return None
def get_metadata(self): """returns a MetaData object, or None raises IOError if unable to read the file""" from io import BytesIO from audiotools.bitstream import BitstreamReader from audiotools.ogg import PacketReader, PageReader reader = PacketReader(PageReader(open(self.filename, "rb"))) identification = reader.read_packet() comment = BitstreamReader(BytesIO(reader.read_packet()), True) if (comment.read_bytes(8) == "OpusTags"): vendor_string = \ comment.read_bytes(comment.read(32)).decode('utf-8') comment_strings = [ comment.read_bytes(comment.read(32)).decode('utf-8') for i in range(comment.read(32)) ] return VorbisComment(comment_strings, vendor_string) else: return None
def total_frames(self): """returns the total PCM frames of the track as an integer""" from audiotools._ogg import PageReader try: reader = PageReader(file(self.filename, "rb")) page = reader.read() pcm_samples = page.granule_position while (not page.stream_end): page = reader.read() pcm_samples = max(pcm_samples, page.granule_position) reader.close() return pcm_samples except (IOError, ValueError): return 0
def total_frames(self): """returns the total PCM frames of the track as an integer""" from audiotools._ogg import PageReader try: with PageReader(open(self.filename, "rb")) as reader: page = reader.read() pcm_samples = page.granule_position while not page.stream_end: page = reader.read() pcm_samples = max(pcm_samples, page.granule_position) return pcm_samples except (IOError, ValueError): return 0
def update_metadata(self, metadata): """takes this track's current MetaData object as returned by get_metadata() and sets this track's metadata with any fields updated in that object raises IOError if unable to write the file """ import os from audiotools import TemporaryFile from audiotools.ogg import (PageReader, PacketReader, PageWriter, packet_to_pages, packets_to_pages) from audiotools.vorbiscomment import VorbisComment from audiotools.bitstream import BitstreamRecorder if (metadata is None): return elif (not isinstance(metadata, VorbisComment)): from .text import ERR_FOREIGN_METADATA raise ValueError(ERR_FOREIGN_METADATA) elif (not os.access(self.filename, os.W_OK)): raise IOError(self.filename) original_ogg = PacketReader(PageReader(file(self.filename, "rb"))) new_ogg = PageWriter(TemporaryFile(self.filename)) sequence_number = 0 #transfer current file's identification packet in its own page identification_packet = original_ogg.read_packet() for (i, page) in enumerate(packet_to_pages( identification_packet, self.__serial_number__, starting_sequence_number=sequence_number)): page.stream_beginning = (i == 0) new_ogg.write(page) sequence_number += 1 #discard the current file's comment packet comment_packet = original_ogg.read_packet() #generate new comment packet comment_writer = BitstreamRecorder(True) comment_writer.build("8u 6b", (3, "vorbis")) vendor_string = metadata.vendor_string.encode('utf-8') comment_writer.build("32u %db" % (len(vendor_string)), (len(vendor_string), vendor_string)) comment_writer.write(32, len(metadata.comment_strings)) for comment_string in metadata.comment_strings: comment_string = comment_string.encode('utf-8') comment_writer.build("32u %db" % (len(comment_string)), (len(comment_string), comment_string)) comment_writer.build("1u a", (1,)) # framing bit #transfer codebooks packet from original file to new file codebooks_packet = original_ogg.read_packet() for page in packets_to_pages( [comment_writer.data(), codebooks_packet], self.__serial_number__, starting_sequence_number=sequence_number): new_ogg.write(page) sequence_number += 1 #transfer remaining pages after re-sequencing page = original_ogg.read_page() page.sequence_number = sequence_number sequence_number += 1 new_ogg.write(page) while (not page.stream_end): page = original_ogg.read_page() page.sequence_number = sequence_number page.bitstream_serial_number = self.__serial_number__ sequence_number += 1 new_ogg.write(page) original_ogg.close() new_ogg.close()